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 }