序列操作 IV(树套树)

xiaoxiao2021-02-28  111

Description 给出序列 a1,a2,…,an(0≤ai≤109),有关序列的两种操作。

ai(1≤i≤n)变成 x(0≤x≤109)。求 al,al+1,…,ar(1≤l≤r≤n)第 k(1≤k≤r-l+1)小。

题解 很显然,查询待修改的区间第k大一般的数据结构已经无法实现。这里给出树套树实现查询的数据结构。

线段树+权值线段树

对于每个线段树上的点维护一颗权值线段树树保存该区间所有数。容易发现对于每个修改操作复杂度是 O(nlog2n) ,而对于查询操作,先将在查询区间内的线段树中的点放入一个数组,由线段树性质得最多 logn 个,然后按照权值线段树求第k大的方法查询,时间复杂度 O(nlog2n) .

注意:线段树开点应开n*4个而不是n*2个。Code: #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> using namespace std; const int Maxn=2e4+5; const int Maxn2=4e6+2e5+50+Maxn; inline int read() { char ch=getchar();int i=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();} return i*f; } int n,m,a[Maxn],tr[Maxn*2],C,lc[Maxn2],rc[Maxn2],sze[Maxn2],cnt0,rk[Maxn*2]; struct node { int val,id,op; friend inline bool operator <(const node &a,const node &b) { return a.val<b.val; } }b[Maxn*2]; struct Q { int op,l,r,val; }q[Maxn]; inline void insert2(int now,int l,int r,int val) { if(l==r) { sze[now]++; return; } int mid=(l+r)>>1; if(val<=mid) { if(!lc[now])lc[now]=++C; insert2(lc[now],l,mid,val); } else { if(!rc[now])rc[now]=++C; insert2(rc[now],mid+1,r,val); } sze[now]=(lc[now]?sze[lc[now]]:0)+(rc[now]?sze[rc[now]]:0); } inline void insert(int k,int l,int r,int pos,int val) { if(!tr[k])tr[k]=++C; insert2(tr[k],1,Maxn*2,val); if(l==r)return; int mid=(l+r)>>1; if(pos<=mid)insert(k<<1,l,mid,pos,val); else insert(k<<1|1,mid+1,r,pos,val); } inline void del2(int now,int l,int r,int val) { if(l==r) { sze[now]--; return; } int mid=(l+r)>>1; if(val<=mid) { if(!lc[now])lc[now]=++C; del2(lc[now],l,mid,val); } else { if(!rc[now])rc[now]=++C; del2(rc[now],mid+1,r,val); } sze[now]=(lc[now]?sze[lc[now]]:0)+(rc[now]?sze[rc[now]]:0); } inline void del(int k,int l,int r,int pos,int val) { if(!tr[k])tr[k]=++C; del2(tr[k],1,Maxn*2,val); if(l==r)return; int mid=(l+r)>>1; if(pos<=mid)del(k<<1,l,mid,pos,val); else del(k<<1|1,mid+1,r,pos,val); } struct num { int l,r,id; num(){} num(int l,int r,int id):l(l),r(r),id(id){} }nums[50]; int C2; inline void getin(int k,int l,int r,int L,int R) { if(l>=L&&r<=R) { nums[++C2].id=tr[k]; nums[C2].l=1; nums[C2].r=Maxn*2; return; } int mid=(l+r)>>1; if(L<=mid)getin(k<<1,l,mid,L,R); if(R>mid)getin(k<<1|1,mid+1,r,L,R); } inline int calclc() { int res=0; for(int i=1;i<=C2;i++) { res+=sze[lc[nums[i].id]]; } return res; } inline void getinlc() { for(int i=1;i<=C2;i++) { nums[i].id=lc[nums[i].id]; nums[i].r=((nums[i].l+nums[i].r)>>1); } } inline void getinrc() { for(int i=1;i<=C2;i++) { nums[i].id=rc[nums[i].id]; nums[i].l=(((nums[i].l+nums[i].r)>>1)+1); } } inline int maxn(num x) { while(x.l!=x.r) { if(sze[rc[x.id]])x.id=rc[x.id],x.l=((x.l+x.r)>>1)+1; else x.id=lc[x.id],x.r=((x.l+x.r)>>1);; } return x.l; } inline int maxlc() { int res=0; for(int i=1;i<=C2;i++) { num x=nums[i]; num t; t.id=lc[x.id]; t.l=x.l; t.r=((x.l+x.r)>>1); res=max(res,maxn(t)); } return res; } inline bool judgerc() { for(int i=1;i<=C2;i++) { if(rc[nums[i].id])return 1; } return 0; } inline int maxnow() { int res=0; for(int i=1;i<=C2;i++) { res=max(res,maxn(num(nums[i].l,nums[i].r,nums[i].id))); } return res; } inline int query(int l,int r,int k) { memset(nums,0,sizeof(nums)); C2=0; getin(1,1,n,l,r); while(1) { int t=calclc(); if(t>k) { getinlc(); continue; } else if(t==k) { return maxlc(); } else if(judgerc()) { k=k-t; getinrc(); } else return maxnow(); } } inline void l_b() { int t=0; sort(b+1,b+cnt0+1); for(int i=1;i<=cnt0;i++) { if(i==1||b[i].val!=b[i-1].val)t++; rk[t]=b[i].val; if(b[i].op)a[b[i].id]=t; else q[b[i].id].val=t; } } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) { b[++cnt0].val=read(); b[cnt0].id=i; b[cnt0].op=1; } for(int i=1;i<=m;i++) { q[i].op=read(); if(q[i].op==0) { q[i].l=read(); q[i].val=read(); b[++cnt0].val=q[i].val; b[cnt0].op=0; b[cnt0].id=i; } else { q[i].l=read(); q[i].r=read(); q[i].val=read(); } } l_b(); for(int i=1;i<=n;i++) { insert(1,1,n,i,a[i]); } for(int i=1;i<=m;i++) { int _=q[i].op; if(_==0) { int d=q[i].l,x=q[i].val; del(1,1,n,d,a[d]); a[d]=x; insert(1,1,n,d,x); } else { int l=q[i].l,r=q[i].r,k=q[i].val; cout<<rk[query(l,r,k)]<<endl; } } }
转载请注明原文地址: https://www.6miu.com/read-96517.html

最新回复(0)