【bzoj4552】【Tjoi2016】【Heoi2016】【排序】【二分答案】【线段树】

来源:互联网 发布:西瓜影音mac版下载 编辑:程序博客网 时间:2024/05/20 17:40

题目大意

给出长度为n的序列,有m个排序操作,对一个区间升序或降序排序,求操作完某一位的值。

题解

一个非常不显然的性质,本题满足二分性质。二分一个答案,如果原数大于或等于答案就标记为1,不然标记为0。排序完可以知道目标位到底是大于等于还是小于答案,适当调整答案即可。

code

#include<set>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)using namespace std;int const maxn=100000;int n,m,q,a[maxn+10],l[maxn+10],r[maxn+10],op[maxn+10],ans[maxn*50+10],flag[maxn*50+10];void change(int now,int l,int r,int l1,int r1,int val){    if(l1>r1)return;    int m=(l+r)/2;    if((flag[now]!=-1)&&(l!=r)){        ans[now*2]=(m-l+1)*flag[now];        ans[now*2+1]=(r-m)*flag[now];        flag[now*2]=flag[now*2+1]=flag[now];        flag[now]=-1;    }    if((l==l1)&&(r==r1)){        ans[now]=(r-l+1)*val;        flag[now]=val;        return;    }else if(r1<=m)change(now*2,l,m,l1,r1,val);    else if(m<l1)change(now*2+1,m+1,r,l1,r1,val);    else{        change(now*2,l,m,l1,m,val);        change(now*2+1,m+1,r,m+1,r1,val);    }    ans[now]=ans[now*2]+ans[now*2+1];}int ask(int now,int l,int r,int l1,int r1){    if(l1>r1)return 0;    int m=(l+r)/2;    if((flag[now]!=-1)&&(l!=r)){        ans[now*2]=(m-l+1)*flag[now];        ans[now*2+1]=(r-m)*flag[now];        flag[now*2]=flag[now*2+1]=flag[now];        flag[now]=-1;    }    if((l==l1)&&(r==r1))return ans[now];    else if(r1<=m)return ask(now*2,l,m,l1,r1);    else if(m<l1)return ask(now*2+1,m+1,r,l1,r1);    else return ask(now*2,l,m,l1,m)+ask(now*2+1,m+1,r,m+1,r1);}int main(){    //freopen("len.in","r",stdin);    //freopen("len.out","w",stdout);    freopen("d.in","r",stdin);    freopen("d.out","w",stdout);    scanf("%d%d",&n,&m);    fo(i,1,n)scanf("%d",&a[i]);    fo(i,1,m)        scanf("%d%d%d",&op[i],&l[i],&r[i]);    scanf("%d",&q);    int le=1,ri=n;    memset(flag,255,sizeof(flag));    while(le!=ri){        int mid=(le+ri+1)/2;        fo(i,1,n)            change(1,1,n,i,i,a[i]>=mid);        fo(i,1,m){            int tmp=ask(1,1,n,l[i],r[i]);            if(op[i]){                change(1,1,n,l[i],l[i]+tmp-1,1);                change(1,1,n,l[i]+tmp,r[i],0);            }else{                change(1,1,n,l[i],r[i]-tmp,0);                change(1,1,n,r[i]-tmp+1,r[i],1);            }        }        if(ask(1,1,n,q,q))le=mid;        else ri=mid-1;    }    printf("%d",le);    return 0;}
1 0