p2824 [HEOI2016/TJOI2016]排序

传送门

分析

二分一个数表示查询位置的数是多少,将序列中大于等于这个数的数赋为1,其余赋为0,对于每一个区间查询区间和(即区间内1的个数),然后区间修改将前/后半部分修改为1,其余修改为0即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int a[100100],d[400400],col[400400],k[100100],x[100100],y[100100];
inline void update(int le,int ri,int wh,int pl,int sum){
      col[wh]=-1;
      if(le==ri){
          d[wh]=sum;
          return;
      }
      int mid=(le+ri)>>1;
      if(mid>=pl)update(le,mid,wh<<1,pl,sum);
        else update(mid+1,ri,wh<<1|1,pl,sum);
      d[wh]=d[wh<<1]+d[wh<<1|1];
      return;
}
inline void build(int le,int ri,int wh,int X,int Y,int sum){
      if(le>=X&&ri<=Y){
          col[wh]=sum;
          d[wh]=(ri-le+1)*sum;
          return;
      }
      int mid=(le+ri)>>1;
      if(col[wh]!=-1){
          col[wh<<1]=col[wh<<1|1]=col[wh];
          d[wh<<1]=col[wh]*(mid-le+1);
          d[wh<<1|1]=col[wh]*(ri-mid);
          col[wh]=-1;
      }
      if(mid>=X)build(le,mid,wh<<1,X,Y,sum);
      if(mid<Y)build(mid+1,ri,wh<<1|1,X,Y,sum);
      d[wh]=d[wh<<1]+d[wh<<1|1];
      return;
}
inline int q(int le,int ri,int wh,int X,int Y){
      if(le>=X&&ri<=Y)return d[wh];
      int mid=(le+ri)>>1,ans=0;
      if(col[wh]!=-1){
          col[wh<<1]=col[wh<<1|1]=col[wh];
          d[wh<<1]=col[wh]*(mid-le+1);
          d[wh<<1|1]=col[wh]*(ri-mid);
          col[wh]=-1;
      }
      if(mid>=X)ans+=q(le,mid,wh<<1,X,Y);
      if(mid<Y)ans+=q(mid+1,ri,wh<<1|1,X,Y);
      d[wh]=d[wh<<1]+d[wh<<1|1];
      return ans;
}
int main(){
      int n,m,i,j,l,r,pos;
      scanf("%d%d",&n,&m);
      for(i=1;i<=n;i++)scanf("%d",&a[i]);
      for(i=1;i<=m;i++)scanf("%d%d%d",&k[i],&x[i],&y[i]);
      scanf("%d",&pos);
      l=1,r=n+1;
      while(r-l>1){
          int mid=(l+r)>>1;
          for(i=1;i<=n;i++)
            update(1,n,1,i,(a[i]>=mid));
          for(i=1;i<=m;i++){
            int sum=q(1,n,1,x[i],y[i]);
            if(k[i]){
                build(1,n,1,x[i],x[i]+sum-1,1);
                build(1,n,1,x[i]+sum,y[i],0);
          }else {
              build(1,n,1,x[i],y[i]-sum,0);
                build(1,n,1,y[i]-sum+1,y[i],1);
          }
        }
        if(q(1,n,1,pos,pos))l=mid;
          else r=mid;
      }
      printf("%d\n",l);
      return 0;
}
posted @ 2018-10-07 19:16  水题收割者  阅读(170)  评论(0编辑  收藏  举报