排序(bzoj 4552)

Description

在2016年,佳媛姐姐喜歡上了數字序列。於是他常常研究關於序列的一些奇奇怪怪的問題,如今他在研究一個難題
,須要你來幫助他。這個難題是這樣子的:給出一個1到n的全排列,如今對這個全排列序列進行m次局部排序,排
序分爲兩種:1:(0,l,r)表示將區間[l,r]的數字升序排序2:(1,l,r)表示將區間[l,r]的數字降序排序最後詢問第q
位置上的數字。

Input

輸入數據的第一行爲兩個整數n和m。n表示序列的長度,m表示局部排序的次數。1 <= n, m <= 10^5第二行爲n個整
數,表示1到n的一個全排列。接下來輸入m行,每一行有三個整數op, l, r, op爲0表明升序排序,op爲1表明降序
排序, l, r 表示排序的區間。最後輸入一個整數q,q表示排序完以後詢問的位置, 1 <= q <= n。1 <= n <= 10^5
,1 <= m <= 10^5
 

Output

 輸出數據僅有一行,一個整數,表示按照順序將所有的部分排序結束後第q位置上的數字。ios

Sample Input

6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3

Sample Output

5
/*
    題解很神奇。
    二分答案k,那麼就是要判斷a[p]與k的大小關係。
    咱們把序列變成0/1序列,0表明該位置的數小於k,1表明大於等於k,對於升降序操做,
    用線段樹維護就能夠了,最後判斷一下。 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 30010
using namespace std;
int a[N],b[N][3],n,m,p;
int sum[N*4],tag[N*4];
void push_up(int k){
    sum[k]=sum[k*2]+sum[k*2+1];
}
void push_down(int k,int l,int r){
    if(tag[k]==-1) return;
    int mid=l+r>>1;
    tag[k*2]=tag[k*2+1]=tag[k];
    sum[k*2]=(mid-l+1)*tag[k];
    sum[k*2+1]=(r-mid)*tag[k];
    tag[k]=-1;
}
void change(int k,int l,int r,int x,int y,int val){
    if(x>y) return;
    if(l>=x&&r<=y){
        sum[k]=(r-l+1)*val;
        tag[k]=val;
        return;
    }
    push_down(k,l,r);
    int mid=l+r>>1;
    if(x<=mid) change(k*2,l,mid,x,y,val);
    if(y>mid) change(k*2+1,mid+1,r,x,y,val);
    push_up(k);
}
int query(int k,int l,int r,int x,int y){
    if(l>=x&&r<=y) return sum[k];
    push_down(k,l,r);
    int mid=l+r>>1,tot=0;
    if(x<=mid) tot+=query(k*2,l,mid,x,y);
    if(y>mid) tot+=query(k*2+1,mid+1,r,x,y);
    return tot;
}
bool check(int mid){
    memset(tag,-1,sizeof(tag));
    memset(sum,0,sizeof(sum));
    for(int i=1;i<=n;i++) change(1,1,n,i,i,a[i]>=mid);
    for(int i=1;i<=m;i++){
        int t=query(1,1,n,b[i][1],b[i][2]);
        if(!b[i][0]){
            change(1,1,n,b[i][1],b[i][2]-t,0);
            change(1,1,n,b[i][2]-t+1,b[i][2],1);
        }
        else {
            change(1,1,n,b[i][1],b[i][1]+t-1,1);
            change(1,1,n,b[i][1]+t,b[i][2],0);
        }
    }
    int t=query(1,1,n,p,p);
    return t;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&b[i][0],&b[i][1],&b[i][2]);
    scanf("%d",&p);
    int l=0,r=n,ans;
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid)) l=mid+1,ans=mid;
        else r=mid-1;
    }
    printf("%d",ans);
    return 0;
}
相關文章
相關標籤/搜索