树套树代码
树状数组套线段树:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 500001 int n,m,ai[maxn],root[maxn],pos[maxn],mis[maxn]; int K,ch[maxn*25][2],dis[25*maxn],tot,to,po,mi,sum,mid; char Cget; inline void in(int &now) { Cget=getchar();now=0; while(Cget>'9'||Cget<'0') Cget=getchar(); while(Cget>='0'&&Cget<='9') { now=now*10+Cget-'0'; Cget=getchar(); } } inline int lowbit(int x) { return x&(-x); } void tree_add(int &now,int l,int r) { if(!now) now=++tot; dis[now]+=K; if(l==r) return ; int mid=l+r>>1; if(to<=mid) tree_add(ch[now][0],l,mid); else tree_add(ch[now][1],mid+1,r); } void add(int x) { while(x<=n) { tree_add(root[x],1,n); x+=lowbit(x); } } int query(int li,int ri) { po=0,mi=0,sum=0,mid=(ri-li>>1)+1; while(ri) { if(root[ri]) { pos[++po]=root[ri]; sum+=dis[pos[po]]; } ri-=lowbit(ri); } while(li) { if(root[li]) { mis[++mi]=root[li]; sum-=dis[mis[mi]]; } li-=lowbit(li); } int l=1,r=n; while(l!=r) { int k=0; for(int i=1;i<=po;i++) { if(pos[i]&&ch[pos[i]][0]) k+=dis[ch[pos[i]][0]]; } for(int i=1;i<=mi;i++) { if(mis[i]&&ch[mis[i]][0]) k-=dis[ch[mis[i]][0]]; } if(k>=mid) { sum=k; for(int i=1;i<=po;i++) if(pos[i]) pos[i]=ch[pos[i]][0]; for(int i=1;i<=mi;i++) if(mis[i]) mis[i]=ch[mis[i]][0]; r=l+r>>1; } else if(sum-k>=mid) { sum-=k; for(int i=1;i<=po;i++) if(pos[i]) pos[i]=ch[pos[i]][1]; for(int i=1;i<=mi;i++) if(mis[i]) mis[i]=ch[mis[i]][1]; l=(l+r>>1)+1; } else return -1; } if(sum>=mid) return l; } int main() { in(n),in(m);int l,r,s,k; for(int i=1;i<=n;i++) in(ai[i]),to=ai[i],K=1,add(i); for(;m--;) { in(l),in(r),in(s),in(k); int p=query(l-1,r); if(p!=-1) s=p; for(;k--;) { in(p); to=ai[p],K=-1,add(p); ai[p]=s; to=s,K=1,add(p); } printf("%d\n",s); } printf("%d\n",query(0,n)); return 0; }
线段树套平衡树:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 500001 struct TreeNodeType { int w,key,size; TreeNodeType *ch[2],*opi; TreeNodeType() { ch[0]=ch[1]=opi=NULL; } }; class SegmentTreeNodeType { private: inline bool getson(TreeNodeType *now) { return (now&&now->opi)?now->opi->ch[1]==now:false; } inline void updata(TreeNodeType *now) { now->size=now->w; if(now->ch[0]) now->size+=now->ch[0]->size; if(now->ch[1]) now->size+=now->ch[1]->size; } inline void rotate(TreeNodeType *now) { bool pos=getson(now); TreeNodeType *opi=now->opi,*fopi=opi->opi; opi->ch[pos]=now->ch[pos^1]; if(opi->ch[pos]) opi->ch[pos]->opi=opi; if(fopi) fopi->ch[getson(opi)]=now; now->ch[pos^1]=opi,opi->opi=now,now->opi=fopi; updata(opi),updata(now); } inline void splay(TreeNodeType *now) { for(TreeNodeType *opi;opi=now->opi;rotate(now)) { if(opi->opi) rotate(getson(now)==getson(opi)?opi:now); } root=now; } public: int l,r,mid,size; TreeNodeType *root; SegmentTreeNodeType() { root=NULL; } void insert(int x) { if(!root) { root=new TreeNodeType; root->key=x,root->size=1,root->w=1; return ; } TreeNodeType *now=root,*opi=NULL; while(1) { if(x==now->key) { now->w++,now->size++,splay(now); return ; } opi=now; if(x<now->key) now=now->ch[0]; else now=now->ch[1]; if(!now) { now=opi->ch[x>opi->key]=new TreeNodeType; now->key=x,now->w=1,now->size=1,now->opi=opi,splay(now); return ; } } } void find(int x) { TreeNodeType *now=root; while(1) { if(!now) return ; if(now->key==x) { splay(now); return ; } if(x<now->key) now=now->ch[0]; else now=now->ch[1]; } } void del() { if(root->w>1) { root->w--,root->size--; return ; } if(!root->ch[0]&&!root->ch[1]) { if(root) delete root; root=NULL; return ; } if(root->ch[0]&&root->ch[1]) { TreeNodeType *now=root->ch[0]; while(now->ch[1]) now=now->ch[1]; now->ch[1]=root->ch[1],now->ch[1]->opi=now; root=root->ch[0];if(root->opi) delete root->opi; root->opi=NULL,splay(now->ch[1]); return ; } if(root->ch[0]) { root=root->ch[0];if(root->opi) delete root->opi; root->opi=NULL; } if(root->ch[1]) { root=root->ch[1];if(root->opi) delete root->opi; root->opi=NULL; } } }; class SegmentTreeNodeType tree[maxn<<2]; int n,m,ai[maxn],use[maxn],p,size; inline void in(int &now) { char Cget=getchar();now=0; while(Cget>'9'||Cget<'0') Cget=getchar(); while(Cget>='0'&&Cget<='9') { now=now*10+Cget-'0'; Cget=getchar(); } } void tree_build(int now,int l,int r) { tree[now].l=l,tree[now].r=r,tree[now].size=r-l+1; for(int i=l;i<=r;i++) tree[now].insert(ai[i]); if(l==r) return ; tree[now].mid=l+r>>1; tree_build(now<<1,l,tree[now].mid); tree_build(now<<1|1,tree[now].mid+1,r); } void tree_query(int now,int l,int r) { if(tree[now].l==l&&tree[now].r==r) { if(tree[now].root) use[++p]=now,size+=tree[now].root->size; return ; } if(r<=tree[now].mid) tree_query(now<<1,l,r); else if(l>tree[now].mid) tree_query(now<<1|1,l,r); else tree_query(now<<1,l,tree[now].mid),tree_query(now<<1|1,tree[now].mid+1,r); } void tree_change(int now,int to,int x) { tree[now].find(ai[to]),tree[now].del(),tree[now].insert(x); if(tree[now].l==tree[now].r) return ; if(to<=tree[now].mid) tree_change(now<<1,to,x); else tree_change(now<<1|1,to,x); } int main() { // freopen("operator.txt","r",stdin); // freopen("output.txt","w",stdout); in(n),in(m);int l,r,s,k,pos,li,ri,kk,op,num; for(int i=1;i<=n;i++) in(ai[i]); tree_build(1,1,n); for(;m--;) { in(li),in(ri),in(s),in(k); size=0,p=0,tree_query(1,li,ri); l=1,r=n,op=((ri-li+1)>>1)+1,num=0; while(l<r) { int mid=l+r>>1; kk=0; for(int i=1;i<=p;i++) { if(!use[i]) continue; tree[use[i]].insert(mid); kk+=tree[use[i]].root->size-1; if(tree[use[i]].root->ch[1]) kk-=tree[use[i]].root->ch[1]->size; tree[use[i]].del(); } kk-=num; if(kk>=op) r=mid,pos=l,size=kk; else if(size-kk>=op) l=mid+1,num+=kk,pos=l,size-=kk; else { pos=-1; break; } } printf("%d\n",pos==-1?s:pos); if(pos!=-1) s=l; for(;k--;) in(pos),tree_change(1,pos,s),ai[pos]=s; } size=0,p=0,tree_query(1,1,n); l=1,r=n,op=(n>>1)+1,num=0; while(l<r) { int mid=l+r>>1; kk=0; for(int i=1;i<=p;i++) { if(!use[i]) continue; tree[use[i]].insert(mid); kk+=tree[use[i]].root->size-1; if(tree[use[i]].root->ch[1]) kk-=tree[use[i]].root->ch[1]->size; tree[use[i]].del(); } kk-=num; if(kk>=op) r=mid,pos=l,size=kk; else if(size-kk>=op) l=mid+1,num+=kk,pos=l,size-=kk; else { pos=-1; break; } } printf("%d\n",pos); return 0; }