luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)

带修改区间K大值

这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做

时空都是$O(nlog^2n)$的(如果离散化了的话),空间可能会被卡,但实际上点数不用开到特别大,N*200也能过

  1 #include<bits/stdc++.h>
  2 #define pa pair<int,int>
  3 #define CLR(a,x) memset(a,x,sizeof(a))
  4 using namespace std;
  5 typedef long long ll;
  6 const int maxn=5e4+10,maxp=maxn*200,inf=1e8;
  7 
  8 inline ll rd(){
  9     ll x=0;char c=getchar();int neg=1;
 10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
 11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
 12     return x*neg;
 13 }
 14 
 15 int root[maxn],ch[maxp][2],v[maxp],pct;
 16 int num[maxn],tmp1[maxn],tmp2[maxn],N,M;
 17 
 18 inline int lowbit(int x){return x&(-x);}
 19 
 20 inline void update(int p){v[p]=v[ch[p][0]]+v[ch[p][1]];}
 21 inline void add(int &p,int l,int r,int x,int y){
 22     if(!p) p=++pct;
 23     if(l==r) v[p]+=y;
 24     else{
 25         int m=l+r>>1;
 26         if(x<=m) add(ch[p][0],l,m,x,y);
 27         else add(ch[p][1],m+1,r,x,y);
 28         update(p);
 29     }
 30 }
 31 inline void change(int x,int y){
 32     int ori=num[x];
 33     for(;x<=N;x+=lowbit(x)){
 34         if(ori!=-1) add(root[x],0,inf,ori,-1);
 35         add(root[x],0,inf,y,1);
 36     }
 37 }
 38 
 39 inline void reset(int x,int y){
 40     for(;y;y-=lowbit(y)) tmp1[y]=root[y];
 41     for(;x;x-=lowbit(x)) tmp2[x]=root[x];
 42 }
 43 inline bool pushdown(int x,int y,bool b){
 44     bool re=0;
 45     for(;y;y-=lowbit(y)) tmp1[y]=ch[tmp1[y]][b],re|=tmp1[y];
 46     for(;x;x-=lowbit(x)) tmp2[x]=ch[tmp2[x]][b],re|=tmp2[x];
 47     return re;
 48 }
 49 
 50 int query1(int l,int r,int x,int y,int k){
 51     if(k<0) return 1;
 52     if(l==r) return 1;
 53     int m=l+r>>1;
 54     if(k<=m){
 55         if(!pushdown(x,y,0)) return 1;
 56         return query1(l,m,x,y,k);
 57     }else{
 58         int w=0;
 59         for(int i=y;i;i-=lowbit(i)) w+=v[ch[tmp1[i]][0]];
 60         for(int i=x;i;i-=lowbit(i)) w-=v[ch[tmp2[i]][0]];
 61         if(!pushdown(x,y,1)) return w+1;
 62         return w+query1(m+1,r,x,y,k);
 63     }
 64 }
 65 int query2(int l,int r,int x,int y,int k){
 66     if(k<=0) return -1;
 67     int w=0;
 68     for(int i=y;i;i-=lowbit(i)) w+=v[tmp1[i]];
 69     for(int i=x;i;i-=lowbit(i)) w-=v[tmp2[i]];
 70     if(w<k) return -1;
 71     if(l==r) return l;
 72     int m=l+r>>1;w=0;
 73     for(int i=y;i;i-=lowbit(i)) w+=v[ch[tmp1[i]][0]];
 74     for(int i=x;i;i-=lowbit(i)) w-=v[ch[tmp2[i]][0]];
 75     if(k<=w){
 76         pushdown(x,y,0);
 77         return query2(l,m,x,y,k);
 78     }else{
 79         pushdown(x,y,1);
 80         return query2(m+1,r,x,y,k-w);
 81     }
 82 }
 83 
 84 int main(){
 85     //freopen(".in","r",stdin);
 86     int i,j,k;
 87     N=rd(),M=rd();
 88     CLR(num,-1);
 89     for(i=1;i<=N;i++){
 90         int x=rd();
 91         change(i,x);num[i]=x;
 92     }
 93     for(i=1;i<=M;i++){
 94         int a=rd(),b=rd(),c=rd();
 95         if(a==3){
 96             change(b,c);num[b]=c;
 97         }else{
 98             int d=rd();
 99             if(a==1){
100                 reset(b-1,c);
101                 printf("%d\n",query1(0,inf,b-1,c,d));
102             }else if(a==2){
103                 reset(b-1,c);
104                 printf("%d\n",query2(0,inf,b-1,c,d));
105             }else if(a==4){
106                 reset(b-1,c);
107                 int rk=query1(0,inf,b-1,c,d);
108                 reset(b-1,c);
109                 if(rk==1) printf("-2147483647\n");
110                 else printf("%d\n",query2(0,inf,b-1,c,rk-1));
111             }else if(a==5){
112                 reset(b-1,c);
113                 int rk=query1(0,inf,b-1,c,d+1);
114                 reset(b-1,c);
115                 int re=query2(0,inf,b-1,c,rk);
116                 if(re==-1) printf("2147483647\n");
117                 else printf("%d\n",re);
118             }
119         }
120     }
121     return 0;
122 }

 

posted @ 2018-10-15 21:21  Ressed  阅读(185)  评论(0编辑  收藏  举报