1.线段树
//Twenty #include<cstdio> #include<cstdlib> #include<cstring> #define lc x<<1 #define rc x<<1|1 #define mid ((l+r)>>1) using namespace std; const int maxn=2e6+10; typedef long long ll; ll a[maxn],segt[maxn<<2],lazy[maxn<<2]; int n,q,qu,xx,yy,zz; void build(int x,int l,int r){ if(l==r){segt[x]=a[l];return ;} build(lc,l,mid);build(rc,mid+1,r); segt[x]=segt[lc]+segt[rc]; } void putdown(int x,int l_len,int r_len){ segt[lc]+=lazy[x]*l_len;lazy[lc]+=lazy[x]; segt[rc]+=lazy[x]*r_len;lazy[rc]+=lazy[x]; lazy[x]=0; } void updata(int x,int l,int r,int ql,int qr,int v){ if(ql<=l&&r<=qr){segt[x]+=(r-l+1)*v;lazy[x]+=v;return;} if(lazy[x]) putdown(x,mid-l+1,r-mid); if(ql<=mid) updata(lc,l,mid,ql,qr,v); if(qr>mid) updata(rc,mid+1,r,ql,qr,v); segt[x]=segt[lc]+segt[rc]; } ll query(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr) return segt[x]; if(lazy[x]) putdown(x,mid-l+1,r-mid); if(qr<=mid) return query(lc,l,mid,ql,qr); else if(ql>mid) return query(rc,mid+1,r,ql,qr); return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); build(1,1,n); scanf("%d",&q); while(q--){ scanf("%d%d%d",&qu,&xx,&yy); if(qu==1){ scanf("%d",&zz); updata(1,1,n,xx,yy,zz); } else printf("%lld\n",query(1,1,n,xx,yy)); } return 0; }
codevs 线段树练习3
//Twenty #include<cstdio> #include<cstdlib> #include<cstring> #define lc x<<1 #define rc x<<1|1 #define mid ((l+r)>>1) using namespace std; const int maxn=1e6+10; typedef long long ll; ll a[maxn],segt[maxn<<2][7],lazy[maxn<<2],temp[7]; int n,q,xx,yy,zz; char qu[10]; using namespace std; void build(int x,int l,int r){ if(l==r) {segt[x][a[l]%7]=1; return ;} build(lc,l,mid);build(rc,mid+1,r); for(int i=0;i<=6;i++){segt[x][i]=segt[lc][i]+segt[rc][i];} } void putdown(int x){ lazy[lc]+=lazy[x]; for(int i=0;i<=6;i++) temp[(i+lazy[x])%7]=segt[lc][i]; for(int i=0;i<=6;i++) segt[lc][i]=temp[i]; lazy[rc]+=lazy[x]; for(int i=0;i<=6;i++) temp[(i+lazy[x])%7]=segt[rc][i]; for(int i=0;i<=6;i++) segt[rc][i]=temp[i]; lazy[x]=0; } void updata(int x,int l,int r,int ql,int qr,int v){ if(ql<=l&&r<=qr) { for(int i=0;i<=6;i++) temp[(i+v)%7]=segt[x][i]; for(int i=0;i<=6;i++) segt[x][i]=temp[i]; lazy[x]+=v; return ; } if(lazy[x]) putdown(x); if(ql<=mid) updata(lc,l,mid,ql,qr,v); if(qr>mid) updata(rc,mid+1,r,ql,qr,v); for(int i=0;i<=6;i++) segt[x][i]=segt[lc][i]+segt[rc][i]; } ll query(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr) return segt[x][0]; if(lazy[x]) putdown(x); if(qr<=mid) return query(lc,l,mid,ql,qr); else if(ql>mid) return query(rc,mid+1,r,ql,qr); return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); scanf("%d",&q); while(q--){ scanf("%s%d%d",&qu,&xx,&yy); if(qu[0]==‘a‘){ scanf("%d",&zz); updata(1,1,n,xx,yy,zz); } else printf("%lld\n",query(1,1,n,xx,yy)); } return 0; }
codevs 线段树练习4
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #define lc x<<1 #define rc x<<1|1 #define mid ((l+r)>>1) const int maxn=200050; typedef long long ll; char s[10]; ll tmp,nn,qs,a,b,c,n,m; ll aa[maxn],sgt[maxn<<2],sgd[maxn<<2],sgx[maxn<<2],lzj[maxn<<2],lzc[maxn<<2]; using namespace std; inline ll read(){ ll ret=0,f=1; char ch=getchar(); while(ch!=‘-‘&&(ch>‘9‘||ch<‘0‘)) ch=getchar(); if(ch==‘-‘) {f=-1;ch=getchar();} for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) ret=ret*10+ch-‘0‘; return ret*f; } void down(int x,int len,int l_len,int r_len){ if(lzc[x]) { if(lzj[x]) tmp=(sgt[x]-lzj[x]*len)/len; else tmp=sgt[x]/len; sgt[lc]=tmp*l_len; lzc[lc]=1; lzj[lc]=0; sgd[lc]=sgx[lc]=tmp; sgt[rc]=tmp*r_len; lzc[rc]=1; lzj[rc]=0; sgd[rc]=sgx[rc]=tmp; lzc[x]=0; } if(lzj[x]){ sgt[lc]+=lzj[x]*l_len; lzj[lc]+=lzj[x]; sgt[rc]+=lzj[x]*r_len; lzj[rc]+=lzj[x]; sgd[lc]+=lzj[x]; sgx[lc]+=lzj[x]; sgd[rc]+=lzj[x]; sgx[rc]+=lzj[x]; lzj[x]=0; } } void build(int x,int l,int r){ if(l==r) {sgd[x]=sgx[x]=sgt[x]=aa[l];return;} build(lc,l,mid); build(rc,mid+1,r); sgt[x]=sgt[lc]+sgt[rc]; sgd[x]=max(sgd[lc],sgd[rc]); sgx[x]=min(sgx[lc],sgx[rc]); } void add(int x,int ql,int qr,int l,int r,int v,int cj){ if(l>=ql&&r<=qr) { if(cj==1) {sgt[x]+=v*(r-l+1); lzj[x]+=v; sgd[x]+=v; sgx[x]+=v; } else {sgt[x]=v*(r-l+1); lzc[x]=1; lzj[x]=0; sgd[x]=sgx[x]=v; } return; } if(lzj[x]||lzc[x]) down(x,r-l+1,mid-l+1,r-mid); if(ql<=mid) add(lc,ql,qr,l,mid,v,cj); if(qr>mid) add(rc,ql,qr,mid+1,r,v,cj); sgt[x]=sgt[lc]+sgt[rc]; sgd[x]=max(sgd[lc],sgd[rc]); sgx[x]=min(sgx[lc],sgx[rc]); } ll query(int x,int ql,int qr,int l,int r,int cs){ if(l>=ql&&r<=qr) {if(cs==1) return sgd[x]; if(cs==2) return sgx[x]; if(cs==3) return sgt[x]; } if(lzj[x]||lzc[x]) down(x,r-l+1,mid-l+1,r-mid); if(qr<=mid) return query(lc,ql,qr,l,mid,cs); else if(ql>mid) return query(rc,ql,qr,mid+1,r,cs); else {if(cs==3)return query(lc,ql,qr,l,mid,cs)+query(rc,ql,qr,mid+1,r,cs); if(cs==1) return max(query(lc,ql,qr,l,mid,cs),query(rc,ql,qr,mid+1,r,cs)); if(cs==2) return min(query(lc,ql,qr,l,mid,cs),query(rc,ql,qr,mid+1,r,cs)); } } int main() { n=read(); m=read(); for(int i=1;i<=n;i++) aa[i]=read(); build(1,1,n); for(int i=1;i<=m;i++){ scanf("%s",&s); a=read();b=read(); if(s[0]==‘a‘) add(1,a,b,1,n,read(),1); else if(s[1]==‘e‘) add(1,a,b,1,n,read(),2); else if(s[1]==‘a‘) printf("%lld\n",query(1,a,b,1,n,1)); else if(s[1]==‘i‘) printf("%lld\n",query(1,a,b,1,n,2)); else printf("%lld\n",query(1,a,b,1,n,3)); } return 0; }
codevs 线段树练习5
2.树状数组
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> using namespace std; const int maxn=500000+5; int n,m,x,y,k,c[maxn]; int lowbit(int x){ return x&(-x); } void add(int x,int v){ for(int i=x;i<=n;i=i+lowbit(i)) c[i]+=v; } int sum(int x){ int ans=0; for(int i=x;i>=1;i=i-lowbit(i)) ans+=c[i]; return ans; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&x); add(i,x); } while(m--){ scanf("%d%d%d",&k,&x,&y); if(k==1) add(x,y); else printf("%d\n",sum(y)-sum(x-1)); } return 0; }
洛谷 树状数组
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> const int maxn=500000+5; using namespace std; int n,m,x,y,k,v,tmp,c[maxn]; int lowbit(int x){ return x&(x^(x-1)); } void add(int x,int v){ for(int i=x;i<=n;i+=lowbit(i)) c[i]+=v; } int sum(int x){ int ans=0; for(int i=x;i>0;i-=lowbit(i)) ans+=c[i]; return ans; } int main() { ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n;i++){ cin>>x; add(i,x-tmp); tmp=x; } while(m--){ cin>>k>>x; if(k==1){ cin>>y>>v; add(x,v); add(y+1,-v); } else{ cout<<sum(x)<<endl; } } return 0; }
洛谷 树状数组2 差分
//Twenty #include<cmath> #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; const int maxn=100025; int sum[maxn],T,q[maxn],qs[maxn],a[maxn],xx,n,sz; int hash(int x){ return lower_bound(a+1,a+sz+1,x)-a;} void add(int x,int v){ for(int i=x;i<=sz;i+=(i&(-i))) sum[i]+=v; } int qry(int x) {int res=0; for(int i=x;i>=1;i-=(i&(-i))) res+=sum[i]; return res;} int kth(int k) { int res=0; for(int i=20;i>=0;i--){ res+=(1<<i); if(res>=sz||k<=sum[res]) res-=(1<<i); //同种数有多个 不能直接查k 故查比k小的+1 else k-=sum[res]; } return a[res+1]; } int main() { scanf("%d",&T); for(int i=1;i<=T;i++){ scanf("%d%d",&q[i],&qs[i]); if(q[i]!=4) a[++sz]=qs[i]; } sort(a+1,a+sz+1); sz=unique(a+1,a+sz+1)-(a+1); for(int i=1;i<=T;i++){ switch(q[i]){ case 1:add(hash(qs[i]),1);break; case 2:add(hash(qs[i]),-1);break; case 3:printf("%d\n",qry(hash(qs[i])-1)+1);break; case 4:printf("%d\n",kth(qs[i]));break; case 5:printf("%d\n",kth(qry(hash(qs[i])-1)));break; //注意区分5,6 case 6:printf("%d\n",kth(qry(hash(qs[i]))+1));break; } } return 0; }
树状数组普通平衡树
3.ZKW线段树
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> const int maxn=200005; int m=1,x,y,T,n,a[maxn<<2]; char q[10]; using namespace std; void build(){ for(;m<=n+1;m<<=1); for(int i=m+1;i<=m+n;i++) scanf("%d",&a[i]); for(int i=m-1;i>0;i--) a[i]=a[i<<1]+a[i<<1|1]; } void add(int x,int v){ int k=x+m; a[k]+=v; for(k>>=1;k;k>>=1) a[k]=a[k<<1]+a[k<<1|1]; } int query(int l,int r){ int ret=0; for(int i=m+l-1,j=m+r+1;i^j^1;i>>=1,j>>=1){ if(~i&1) ret+=a[i^1]; if(j&1) ret+=a[j^1]; } return ret; } int main() { scanf("%d",&T); for(int t=1;t<=T;t++){ scanf("%d",&n); cout<<"Case "<<t<<":"<<endl; build(); for(;;){ scanf("%s",&q); if(q[0]==‘E‘) break; scanf("%d%d",&x,&y); if(q[0]==‘A‘) add(x,y); else if(q[0]==‘S‘) add(x,-y); else printf("%d\n",query(x,y)); } m=1;memset(a,0,sizeof(a)); } return 0; }
zkw线段树 sum
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> const int maxn=200005; int f,m=1,x,y,T,n,a[maxn<<2]; char q[5]; using namespace std; void build(){ for(;m<=n+1;m<<=1); for(int i=m+1;i<=m+n;i++) scanf("%d",&a[i]); for(int i=m-1;i>0;i--) a[i]=max(a[i<<1],a[i<<1|1]); } void add(int x,int v){ int k=x+m; a[k]=v; for(k>>=1;k;k>>=1) a[k]=max(a[k<<1],a[k<<1|1]); } int query(int l,int r){ int ret=0; for(int i=m+l-1,j=m+r+1;i^j^1;i>>=1,j>>=1){ if(~i&1) ret=max(ret,a[i^1]); if(j&1) ret=max(ret,a[j^1]); } return ret; } int main() { while(scanf("%d%d",&n,&f)!=EOF){ build(); while(f--){ scanf("%s%d%d",&q,&x,&y); if(q[0]==‘U‘) add(x,y); else printf("%d\n",query(x,y)); } m=1;memset(a,0,sizeof(a)); } return 0; }
zkw线段树 max
4.ST表
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> const int maxn=1e6+299; using namespace std; int n,m,l,r,st[maxn][20]; void make_st(){ for(int j=1;j<=20;j++) for(int i=1;i+(1<<j)-1<=n;i++) st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]); } int query(int l,int r){ int k=0; while(l+(1<<k)-1<=r) k++; if(k) k--; return max(st[l][k],st[r-(1<<k)+1][k]); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&st[i][0]); make_st(); while(m--){ scanf("%d%d",&l,&r); printf("%d\n",query(l,r)); } return 0; }
st表
5.主席树
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> const int maxn=100005; int sz,T,n,m,rt[maxn],tot,lc[maxn*20],rc[maxn*20],sum[maxn*20],a[maxn],b[maxn]; using namespace std; void update(int &o,int l,int r,int last,int v){ o=++tot; lc[o]=lc[last]; rc[o]=rc[last]; sum[o]=sum[last]+1; if(l==r) return; int mid=(l+r)>>1; if(v<=mid) update(lc[o],l,mid,lc[last],v); else update(rc[o],mid+1,r,rc[last],v); } int query(int ql,int qr,int l,int r,int k){ if(l==r) return l; int mid=(l+r)>>1; int cnt=sum[lc[qr]]-sum[lc[ql]]; if(cnt>=k) return query(lc[ql],lc[qr],l,mid,k); else return query(rc[ql],rc[qr],mid+1,r,k-cnt); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]);b[i]=a[i];} sort(b+1,b+n+1); sz=unique(b+1,b+n+1)-(b+1); tot=0; rt[0]=++tot; //build(rt[0],1,sz); for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+sz+1,a[i])-b; for(int i=1;i<=n;i++) update(rt[i],1,sz,rt[i-1],a[i]); for(int i=1;i<=m;i++){ int l,r,k;scanf("%d%d%d",&l,&r,&k); printf("%d\n",b[query(rt[l-1],rt[r],1,sz,k)]); } return 0; }
主席树
6.树链剖分
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #define rc x<<1|1 #define lc x<<1 #define mid ((l+r)>>1) using namespace std; const int maxn=150005; int x,y,z,k,n,q,s,mod,w[maxn],fir[maxn],next[maxn*2],to[maxn*2],father[maxn],R[maxn],size[maxn],tid[maxn]; int top[maxn],e[maxn],in[maxn],segt[maxn<<2],lazy[maxn<<2]; int ecnt,tot; inline void add(int u,int v){ next[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;in[u]++; next[++ecnt]=fir[v];fir[v]=ecnt;to[ecnt]=u;in[v]++; } void down(int x,int l_len,int r_len){ if(l_len) lazy[lc]+=lazy[x]%mod, segt[lc]+=l_len*lazy[x]%mod; if(r_len) lazy[rc]+=lazy[x]%mod, segt[rc]+=r_len*lazy[x]%mod; lazy[x]=0; } void change(int x,int l,int r,int ql,int qr,int v){ if(l>=ql&&r<=qr) {segt[x]+=v*(r-l+1);lazy[x]+=v;lazy[x]%=mod;return;} if(lazy[x]) down(x,mid-l+1,r-mid); if(ql<=mid) change(lc,l,mid,ql,qr,v); if(qr>mid) change(rc,mid+1,r,ql,qr,v); segt[x]=(segt[lc]+segt[rc])%mod; } int query(int x,int l,int r,int ql,int qr){ if(l>=ql&&r<=qr) return segt[x]; if(lazy[x]) down(x,mid-l+1,r-mid); if(qr<=mid) return query(lc,l,mid,ql,qr)%mod; if(ql>mid) return query(rc,mid+1,r,ql,qr)%mod; return (query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr))%mod; } void dfs(int x,int fa){ father[x]=fa;R[x]=R[fa]+1;size[x]=1; for(int i=fir[x];i;i=next[i]){ if(to[i]!=fa){ dfs(to[i],x); size[x]+=size[to[i]]; } } } void dfs2(int x){ tid[x]=++tot; change(1,1,n,tot,tot,w[x]); int mson=0; if(in[x]==1&&x!=s){ e[x]=x; return; } for(int i=fir[x];i;i=next[i]) if(size[to[i]]<size[x]&&size[to[i]]>size[mson]) mson=to[i]; top[mson]=top[x]; dfs2(mson); e[x]=e[mson]; for(int i=fir[x];i;i=next[i]){ if(size[to[i]]<size[x]&&to[i]!=mson){ top[to[i]]=to[i]; dfs2(to[i]); e[x]=e[to[i]]; } } } void schange(int x,int y,int z){ while(top[x]!=top[y]){ if(R[top[x]]<R[top[y]]) swap(x,y); change(1,1,n,tid[top[x]],tid[x],z); x=father[top[x]]; } if(tid[x]>tid[y]) swap(x,y); change(1,1,n,tid[x],tid[y],z); } int squery(int x,int y){ int ret=0; while(top[x]!=top[y]){ if(R[top[x]]<R[top[y]]) swap(x,y); ret+=query(1,1,n,tid[top[x]],tid[x]); ret=ret%mod; x=father[top[x]]; } if(tid[x]>tid[y]) swap(x,y); ret+=query(1,1,n,tid[x],tid[y]); ret=ret%mod; return ret; } int main() { scanf("%d%d%d%d",&n,&q,&s,&mod); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); add(x,y); } father[s]=s;top[s]=s; dfs(s,s);dfs2(s); for(int i=1;i<=q;i++){ scanf("%d",&k); if(k==1){ scanf("%d%d%d",&x,&y,&z); schange(x,y,z); } else if(k==2){ scanf("%d%d",&x,&y); printf("%d\n",squery(x,y)); } else if(k==3){ scanf("%d%d",&x,&z); change(1,1,n,tid[x],tid[e[x]],z); } else{ scanf("%d",&x); printf("%d\n",query(1,1,n,tid[x],tid[e[x]])); } } return 0; }
树链剖分
7.treap
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<ctime> const int maxn=100050; int root,T,qs,xx,tot,v[maxn],l[maxn],r[maxn],hr[maxn],sz[maxn]; using namespace std; void update(int x) {sz[x]=sz[l[x]]+sz[r[x]]+1;} inline int read(){ int ret=0,f=1;char ch=getchar(); while(ch!=‘-‘&&ch<‘0‘||ch>‘9‘) ch=getchar(); if(ch==‘-‘) f=-1,ch=getchar(); for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) ret=ret*10+ch-‘0‘; return ret*f; } void left(int &x){ int y=r[x]; r[x]=l[y]; l[y]=x; update(x); x=y; update(x); } void right(int &x){ int y=l[x]; l[x]=r[y]; r[y]=x; update(x); x=y; update(x); } void del(int &y,int x){ if(!y) return; if(v[y]==x){ if(!l[y]) y=r[y]; else if(!r[y]) y=l[y]; else{ if(hr[l[y]]<hr[r[y]]){ right(y); del(r[y],x); } else{ left(y); del(l[y],x); } update(y); } } else { if(x<v[y]) del(l[y],x); else del(r[y],x); update(y); } } int insert(int &y,int x) { if(!y) { v[y=++tot]=x; hr[y]=rand(); l[y]=0;r[y]=0; } else if(v[y]>x){ insert(l[y],x); if(hr[l[y]]<hr[y]) right(y); } else { insert(r[y],x); if(hr[r[y]]<hr[y]) left(y); } update(y); } int rank(int y,int x){ int res=1; for(;y;){ if(v[y]<x) res+=sz[l[y]]+1,y=r[y]; else y=l[y]; } return res; } int kth(int y,int x){ for(;y;){ if(sz[l[y]]+1==x) return v[y]; else if(sz[l[y]]+1<x) x-=(sz[l[y]]+1),y=r[y]; else y=l[y]; } return -1; } int pre(int x){ int res=-1; for(int y=root;y;){ if(v[y]<x) res=v[y],y=r[y]; else y=l[y]; } return res; } int nxt(int x){ int res=-1; for(int y=root;y;){ if(v[y]>x) res=v[y],y=l[y]; else y=r[y]; } return res; } int main() { scanf("%d",&T); srand(time(0)); while(T--){ scanf("%d%d",&qs,&xx); switch(qs){ case 1:insert(root,xx);break; case 2:del(root,xx);break; case 3:printf("%d\n",rank(root,xx));break; case 4:printf("%d\n",kth(root,xx));break; case 5:printf("%d\n",pre(xx));break; case 6:printf("%d\n",nxt(xx));break; } } return 0; }
treap
8.splay
//Twenty #include <cstdio> #define Maxn 1000000 using namespace std; int f[Maxn]; int ch[Maxn][2]; int key[Maxn]; int cnt[Maxn]; int siz[Maxn]; int sz,root; void clear(int x) { ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=siz[x]=0; } int getson(int x) {return ch[f[x]][1]==x;} void update(int x) { siz[x]=cnt[x]; if (ch[x][0]) siz[x]+=siz[ch[x][0]]; if (ch[x][1]) siz[x]+=siz[ch[x][1]]; } int rotate(int x) { int fa=f[x],fafa=f[fa],k=getson(x); ch[fa][k]=ch[x][k^1];f[ch[fa][k]]=fa; ch[x][k^1]=fa;f[fa]=x;f[x]=fafa; if (fafa) ch[fafa][ch[fafa][1]==fa]=x; update(fa);update(x); } void splay(int x) { for (int fa;fa=f[x];rotate(x)) if (f[fa]) rotate(getson(x)==getson(fa) ? fa : x); root=x; } int pre() { int now=ch[root][0]; while(ch[now][1]) now=ch[now][1]; return now; } int nex() { int now=ch[root][1]; while(ch[now][0]) now=ch[now][0]; return now; } int findpos(int v) { int now=root,ans=0; while(1) { if (v<key[now]) now=ch[now][0]; else { ans+=ch[now][0]?siz[ch[now][0]]:0; if (v==key[now]) { splay(now); return ans+1; } ans+=cnt[now]; now=ch[now][1]; } } } int findx(int x) { int now=root; while(1) { if (ch[now][0] && x<=siz[ch[now][0]]) now=ch[now][0]; else { int temp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now]; if (x<=temp) return key[now]; x-=temp; now=ch[now][1]; } } } void create(int v) { sz++; ch[sz][0]=ch[sz][1]=f[sz]=0; key[sz]=v; cnt[sz]=1; siz[sz]=1; } void insert(int v) { if (!root) create(v),root=sz; else { int now=root,fa=0; while(1) { if (key[now]==v) { cnt[now]++; splay(now); break; } fa=now; now=ch[fa][v>key[fa]]; if (!now) { create(v); f[sz]=fa; ch[fa][v>key[fa]]=sz; update(fa); splay(sz); break; } } } } void del(int x) { int t=findpos(x); if (cnt[root]>1) { cnt[root]--; update(root); return; } if (!ch[root][0] && !ch[root][1]) { clear(root); root=0; return; } if (!ch[root][1]) { int temp=root; root=ch[root][0]; f[root]=0; clear(temp); return; } else if (!ch[root][0]) { int temp=root; root=ch[root][1]; f[root]=0; clear(temp); return; } int pre1=pre(),temp=root; splay(pre1); f[ch[temp][1]]=root; ch[root][1]=ch[temp][1]; clear(temp); update(root); } int main() { int n,opt,x; scanf("%d",&n); for (int i=1;i<=n;++i) { scanf("%d%d",&opt,&x); switch(opt) { case 1: insert(x); break; case 2: del(x); break; case 3: printf("%d\n",findpos(x)); break; case 4: printf("%d\n",findx(x)); break; case 5: insert(x); printf("%d\n",key[pre()]); del(x); break; case 6: insert(x); printf("%d\n",key[nex()]); del(x); break; } } }
splay
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #define lc ch[x][0] #define rc ch[x][1] using namespace std; const int maxn=100005; int n,T,l,r,root,cnt,flip[maxn],ch[maxn][2],p[maxn],sz[maxn]; void update(int x) {sz[x]=sz[lc]+sz[rc]+1;} void down(int x){ if(!flip[x]) return; swap(lc,rc); flip[lc]^=1;flip[rc]^=1; flip[x]=0; } int kth(int x,int a){ for(;x;){ down(x); int k=sz[lc]+1; if(k==a) return x; if(k<a) a-=k,x=rc; else x=lc; } } void rotate(int x){ int y=p[x],z=p[y]; if(z) ch[z][y==ch[z][1]]=x; p[x]=z; l=(x==ch[y][1]),r=l^1; ch[y][l]=ch[x][r]; p[ch[y][l]]=y; ch[x][r]=y; p[y]=x; update(y); update(x); } void splay(int x,int FA){ if(p[x]!=FA){ static int s[maxn],top=0; for(int i=x;i;i=p[i]) s[++top]=i; while(top) down(s[top--]); } for(;p[x]!=FA;rotate(x)){ int y=p[x],z=p[y]; if(z!=FA){ ((ch[z][1]==y)^(ch[y][1]==x))?rotate(x):rotate(y); } } if(!FA) root=x; } void rever(int l,int r){ l=kth(root,l);r=kth(root,r+2); splay(l,0); splay(r,l); int x=ch[root][1]; flip[lc]^=1; int now=ch[r][0]; ch[r][0]=0; update(r); update(root); x=kth(root,n-sz[now]+1); splay(x,0); x=rc; lc=now; update(x); update(root); } int build(int n){ if(!n) return 0; l=build(n>>1); int x=++cnt; lc=l; r=build(n-(n>>1)-1); rc=r; if(lc) p[lc]=x; if(rc) p[rc]=x; update(x); return x; } void print(int x){ if(!x) return; down(x); print(lc); if(x>=2&&x<=n+1) printf("%d ",x-1); print(rc); } int main() { scanf("%d%d",&n,&T); root=build(n+2); while(T--){ scanf("%d%d",&l,&r); rever(l,r); } print(root); return 0; }
文艺平衡树
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #define lc ch[x][0] #define rc ch[x][1] using namespace std; const int maxn=100005; int aa,bb,tot,root,n,m,ch[maxn][2],p[maxn],flip[maxn],sz[maxn]; void update(int x) {sz[x]=sz[lc]+sz[rc]+1;} void down(int x){ if(!flip[x]) return; swap(lc,rc); flip[x]^=1; flip[lc]^=1; flip[rc]^=1; } void rotate(int x){ int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1; if(z) ch[z][y==ch[z][1]]=x; p[x]=z; ch[y][l]=ch[x][r]; p[ch[y][l]]=y; ch[x][r]=y; p[y]=x; update(y); update(x); } void splay(int x,int FA){ if(p[x]==FA) return; static int s[maxn],top; for(int i=x;i;i=p[i]) s[++top]=i; while(top) down(s[top--]); for(;p[x]!=FA;rotate(x)){ int y=p[x],z=p[y]; if(z!=FA){ ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y); } } if(FA==0) root=x; } int build(int n){ if(!n) return 0; int ll=build(n>>1); int x=++tot; lc=ll; rc=build(n-(n>>1)-1); if(lc) p[lc]=x; if(rc) p[rc]=x; update(x); return x; } int kth(int k){ for(int x=root;x;){ down(x); if(sz[lc]+1==k) return x; if(sz[lc]+1<k) k-=(sz[lc]+1),x=rc; else x=lc; } } void print(int x){ if(!x) return; down(x); print(lc); if(x>1&&x<n+2) printf("%d\n",x-1); print(rc); } void rever(int l,int r){ int ll=kth(l),rr=kth(r+2); //print(root); splay(ll,0); splay(rr,ll); flip[ch[rr][0]]^=1; int now=ch[rr][0]; ch[rr][0]=0; update(rr); update(root); int x=kth(n-sz[now]+1); splay(x,0); x=rc; lc=now; p[now]=x; update(x); update(root); } int main() { scanf("%d%d",&n,&m); root=build(n+2); while(m--){ scanf("%d%d",&aa,&bb); rever(aa,bb); } print(root); return 0; }
文艺平衡树加强
9.LCT
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #define lc ch[x][0] #define rc ch[x][1] const int maxn=3*1e5+5; using namespace std; int k,tot,n,m,a,b,p[maxn],ch[maxn][2],v[maxn],sum[maxn],flip[maxn]; inline int read(){ int ret=0,f=1; char ch=getchar(); while((ch!=‘-‘)&&(ch<‘0‘||ch>‘9‘)) ch=getchar(); if(ch==‘-‘) f=-1,ch=getchar(); for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) ret=ret*10+ch-‘0‘; return ret*f; } void update(int x) {sum[x]=v[x]; if(lc)sum[x]^=sum[lc]; if(rc)sum[x]^=sum[rc];} void down(int x){ if(!flip[x]) return ; swap(lc,rc); flip[lc]^=1; flip[rc]^=1; flip[x]^=1; } bool isroot(int x) {return (ch[p[x]][0]!=x)&&(ch[p[x]][1]!=x);} void rotate(int x){ int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1; if(!isroot(y)) ch[z][y==ch[z][1]]=x; p[x]=z; ch[y][l]=ch[x][r]; p[ch[x][r]]=y; ch[x][r]=y; p[y]=x; update(y); update(x); } void splay(int x){ static int s[maxn],top; s[top=1]=x; for(int i=x;!isroot(i);i=p[i]) s[++top]=p[i]; while(top) down(s[top--]); for(;!isroot(x);rotate(x)){ int y=p[x],z=p[y]; if(!isroot(y)){ ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y); } } } void access(int x){ for(int t=0;x;x=p[t=x]){ splay(x); ch[x][1]=t; update(x); } } int findroot(int x){ access(x); splay(x); while(lc) x=lc; return x; } bool lt(int a,int b){ return findroot(a)==findroot(b); } void newroot(int x){ access(x); splay(x);//fasdgggggggggggggggg flip[x]^=1; } void link(int a,int b){ if(lt(a,b)) return; newroot(a); p[a]=b; } void del(int a,int b){ newroot(a);//splay(a); access(b); //if(p[b]==a) ch[a][b==ch[a][1]]=0; splay(b);//sdgadfffgaggggggggggfjdgfjhfghgf if(ch[b][0]==a) ch[b][0]=p[a]=0; } void change(int a,int b){ splay(a);//newroot(a); v[a]=b; update(a); } void query(int a,int b){ newroot(a);//splay(a); access(b); splay(b);//gdfgfgb gshfthhhhhhhhhhhhhhhhhhhhh printf("%d\n",sum[b]); } int main() { n=read(); m=read(); for(int i=1;i<=n;i++){ a=read(); v[i]=sum[i]=a; } while(m--){ k=read(); a=read(); b=read(); switch(k){ case 0:query(a,b);break; case 1:link(a,b); break; case 2:del(a,b); break; case 3:change(a,b);break; } } return 0; }
LCT
10.左偏树
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #define lc ch[x][0] #define rc ch[x][1] const int maxn=100000+299; using namespace std; int n,m,k,x,y,ch[maxn][2],fa[maxn],v[maxn],bo[maxn],dis[maxn]; int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } int merge(int x,int y){ if(!x) {return y;} if(!y) {return x;} if(v[x]>v[y]) swap(x,y); fa[y]=x; rc=merge(rc,y); if(dis[rc]>dis[lc]) swap(lc,rc); if(!rc) dis[x]=0; else dis[x]=dis[rc]+1; return x; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&v[i]); fa[i]=i; } while(m--){ scanf("%d%d",&k,&x); if(k==1){ scanf("%d",&y); if(!bo[x]&&!bo[y]&&find(x)!=find(y)) x=merge(find(x),find(y)); } else{ if(bo[x]) cout<<-1<<endl; else{ x=find(x); printf("%d\n",v[x]); fa[lc]=lc; fa[rc]=rc; if(lc&&rc) lc=merge(lc,rc); if(lc) fa[x]=lc; else fa[x]=rc; lc=rc=0; } bo[x]=1; } } return 0; }
左偏树
11.KD-Tree
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> const int maxn=500000+299; using namespace std; int ans=1e9+7,now,nowx,nowmax,nowmin,root,y,n,D,data[maxn][2][2],ch[maxn][2]; struct node{ int d[2]; friend bool operator <(const node&A,const node&B){ return A.d[D]<B.d[D]; } }a[maxn],T; void update(int x){ for(int i=0;i<2;i++) for(int j=0;j<2;j++) data[x][i][j]=a[x].d[i]; for(int i=0;i<2;i++) if(y=ch[x][i]) for(int j=0;j<2;j++){ data[x][j][0]=min(data[x][j][0],data[y][j][0]); data[x][j][1]=max(data[x][j][1],data[y][j][1]); } } int build(int l,int r,int k){ if(l>r) return 0; int mid=(l+r)>>1; D=k; nth_element(a+l,a+mid,a+r+1); ch[mid][0]=build(l,mid-1,k^1); ch[mid][1]=build(mid+1,r,k^1); update(mid); return mid; } int max_dis(int x){ if(!x) return -1e9; int res=0; for(int i=0;i<2;i++) res+=max(abs(T.d[i]-data[x][i][0]),abs(data[x][i][1]-T.d[i])); return res; } int dis(int x){ return abs(a[x].d[0]-T.d[0])+abs(a[x].d[1]-T.d[1]); } int min_dis(int x){ if(!x) return 1e9; int res=0; for(int i=0;i<2;i++) res+=max(T.d[i]-data[x][i][1],0); for(int i=0;i<2;i++) res+=max(data[x][i][0]-T.d[i],0); return res; } void qrymin(int x){ if(!x) return; if(x!=nowx) nowmin=min(dis(x),nowmin); int lc=ch[x][0],rc=ch[x][1]; int l=min_dis(lc); int r=min_dis(rc); if(l>r) {swap(lc,rc);swap(l,r);} if(lc&&l<nowmin) qrymin(lc); if(rc&&r<nowmin) qrymin(rc); } void qrymax(int x){ if(!x) return; if(x!=nowx) nowmax=max(dis(x),nowmax); int lc=ch[x][0],rc=ch[x][1]; int l=max_dis(lc); int r=max_dis(rc); if(l<r) {swap(lc,rc);swap(l,r);} if(lc&&l>nowmax) qrymax(lc); if(rc&&r>nowmax) qrymax(rc); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&a[i].d[0],&a[i].d[1]); root=build(1,n,0); for(int i=1;i<=n;i++){ nowx=i; T=a[i]; nowmax=-1e9+7; nowmin=1e9+7; qrymin(root); qrymax(root); ans=min(ans,nowmax-nowmin); } printf("%d\n",ans); return 0; }
KD-Tree
12.
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #define lc x<<1 #define rc x<<1|1 #define mid ((l+r)>>1) const int maxn=10005; bool st; int tot,T,ql,qr,qq,aa[maxn],n,m,sg[maxn<<2],ls[maxn*450],rs[maxn*450],sgq[maxn*450],que[maxn]; int nn=1e9; char qs[5]; bool ed; using namespace std; inline int read() { int res=0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘) ch=getchar(); for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) res=res*10+ch-‘0‘; return res; } void buq(int &x,int l,int r,int v,int kk){ if(!x) x=++tot; if(l==r) {if(kk) sgq[x]++; else sgq[x]--; return;} if(v<=mid) buq(ls[x],l,mid,v,kk); else buq(rs[x],mid+1,r,v,kk); sgq[x]=sgq[ls[x]]+sgq[rs[x]]; } void build(int x,int l,int r){ for(int i=l;i<=r;i++) buq(sg[x],1,nn,aa[i],1); if(l==r) return; build(lc,l,mid); build(rc,mid+1,r); } void change(int x,int l,int r,int xw,int jv,int xv){ buq(sg[x],1,nn,jv,0); buq(sg[x],1,nn,xv,1); if(l==r) return; if(xw<=mid) change(lc,l,mid,xw,jv,xv); else change(rc,mid+1,r,xw,jv,xv); } void query(int x,int l,int r,int ql,int qr){ if(l>=ql&&r<=qr) {que[++que[0]]=sg[x];return;} if(qr<=mid) query(lc,l,mid,ql,qr); else if(ql>mid) query(rc,mid+1,r,ql,qr); else {query(lc,l,mid,ql,qr); query(rc,mid+1,r,ql,qr);} } int qry(int ql,int qr,int k){ que[0]=0; query(1,1,n,ql,qr); int l=1,r=nn; for(;;){ int now=0; for(int i=1;i<=que[0];i++) now+=sgq[ls[que[i]]]; if(now>=k) { for(int i=1;i<=que[0];i++) que[i]=ls[que[i]]; r=mid; } else{ for(int i=1;i<=que[0];i++) que[i]=rs[que[i]]; k-=now; l=mid+1; } if(l==r) return l; } } int main() { //printf("%d\n",(&ed-&st)/1024/1024); //for(;;); //freopen("dynamic9.in","r",stdin); //freopen("aa.out","w",stdout); /*scanf("%d",&T); while(T--){*/ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) {aa[i]=read(); aa[i]++; } /*sort(aa+1,aa+n+1); nn=unique(aa+1,aa+n+1)-(aa+1);*/ //for(int i=1;i<=n;i++) {bb[i]=lower_bound(aa+1,aa+n+1,bb[i])-aa;} build(1,1,n); while(m--){ scanf("%s",qs); ql=read(); qr=read(); if(qs[0]==‘C‘){ qr++; change(1,1,n,ql,aa[ql],qr); aa[ql]=qr; } else{ qq=read();//scanf("%d",&qq); printf("%d\n",qry(ql,qr,qq)-1); } } /*if(T){ tot=0; memset(aa,0,sizeof(aa)); memset(sg,0,sizeof(sg)); memset(sgq,0,sizeof(sgq)); memset(ls,0,sizeof(ls)); memset(rs,0,sizeof(rs)); } }*/ return 0; }
树套树
时间: 2025-01-31 20:16:26