人生第一道树套树的题,卡了3个小时。。。。。。。。
简直是人生耻辱啊。
目测从此患上了树套树恐惧症。
还有就是为毛我写的Treap这么慢(=。=)竟然跑了8秒多,感觉要跪啊。
还有这200多行的代码看得我好虚啊。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<ctime> #include<queue> #include<cctype> using namespace std; const int N=50000+5; const int M=2000000+5; int lc[M],rc[M],key[M],sz[M],fix[M],cnt; queue<int>q; int id(){ if(q.size()){ int t=q.front();q.pop(); return t; }else return ++cnt; } void pushup(int x){ sz[x]=sz[lc[x]]+sz[rc[x]]+1; } void lturn(int &x){ int k=rc[x];rc[x]=lc[k];lc[k]=x;sz[k]=sz[x];pushup(x);x=k; } void rturn(int &x){ int k=lc[x];lc[x]=rc[k];rc[k]=x;sz[k]=sz[x];pushup(x);x=k; } struct treap{ int root; treap(){ root=0; } void insert(int &x,int v){ if(!x){ key[x=id()]=v;sz[x]=1;lc[x]=rc[x]=0;fix[x]=rand(); } else{ sz[x]++; if(v<key[x]){ insert(lc[x],v); if(fix[lc[x]]<fix[x])rturn(x); }else{ insert(rc[x],v); if(fix[rc[x]]<fix[x])lturn(x); } } } void insert(int x){ insert(root,x); } void del(int &x,int v){ if(!x)return; if(key[x]==v){ if(!lc[x]||!rc[x])q.push(x),x=lc[x]+rc[x]; else if(fix[lc[x]]<fix[rc[x]])rturn(x),sz[x]--,del(rc[x],v); else lturn(x),sz[x]--,del(lc[x],v); }else{ sz[x]--; if(v<key[x])del(lc[x],v); else del(rc[x],v); } } void modify(int x,int y){ del(root,x); insert(root,y); } int rank(int x,int k){ if(!x)return 0; if(k<=key[x])return rank(lc[x],k); else return sz[lc[x]]+1+rank(rc[x],k); } int rank(int x){ return rank(root,x); } int suc(int x,int k){ if(!x)return k; if(key[x]<=k)return suc(rc[x],k); else{ int r=suc(lc[x],k); if(r==k)return key[x]; else return r; } } int suc(int k){ return suc(root,k); } int pre(int x,int k){ if(!x)return k; if(key[x]>=k)return pre(lc[x],k); else{ int r=pre(rc[x],k); if(r==k)return key[x]; else return r; } } int pre(int k){ return pre(root,k); } void travel(int x){ if(!x)return; travel(lc[x]); printf("%d ",key[x]); travel(rc[x]); } void travel(){ travel(root); } }; struct Node{ int l,r,lc,rc; treap t; }; struct SegmentTree{ int cnt,root; Node tr[N<<2]; SegmentTree(){ cnt=0; root=0; } void build(int &o,int l,int r){ o=++cnt; tr[o].l=l;tr[o].r=r; if(l==r)return; else{ int mid=l+r>>1; build(tr[o].lc,l,mid); build(tr[o].rc,mid+1,r); } } void build(int n){ build(root,1,n); } void insert(int o,int p,int x){ tr[o].t.insert(x); int l=tr[o].l,r=tr[o].r; if(l==r)return; else{ int mid=l+r>>1; if(p<=mid)insert(tr[o].lc,p,x); else insert(tr[o].rc,p,x); } } void modify(int o,int p,int x,int y){ //printf("%d %d\n",x,y); tr[o].t.modify(x,y); int l=tr[o].l,r=tr[o].r; if(l==r)return; else{ int mid=l+r>>1; if(p<=mid)modify(tr[o].lc,p,x,y); else modify(tr[o].rc,p,x,y); } } int rank(int o,int a,int b,int x){ int l=tr[o].l,r=tr[o].r; if(l==a&&b==r)return tr[o].t.rank(x); else{ int mid=l+r>>1; if(b<=mid)return rank(tr[o].lc,a,b,x); else if(mid<a)return rank(tr[o].rc,a,b,x); else return rank(tr[o].lc,a,mid,x)+rank(tr[o].rc,mid+1,b,x); } } int pre(int o,int a,int b,int x){ int l=tr[o].l,r=tr[o].r; if(l==a&&b==r)return tr[o].t.pre(x); else{ int mid=l+r>>1; if(b<=mid)return pre(tr[o].lc,a,b,x); else if(mid<a)return pre(tr[o].rc,a,b,x); else{ int lans=pre(tr[o].lc,a,mid,x),rans=pre(tr[o].rc,mid+1,b,x); if(lans==x)return rans; if(rans==x)return lans; return max(lans,rans); } } } int suc(int o,int a,int b,int x){ int l=tr[o].l,r=tr[o].r; if(l==a&&b==r)return tr[o].t.suc(x); else{ int mid=l+r>>1; if(b<=mid)return suc(tr[o].lc,a,b,x); else if(mid<a)return suc(tr[o].rc,a,b,x); else{ int lans=suc(tr[o].lc,a,mid,x),rans=suc(tr[o].rc,mid+1,b,x); if(lans==x)return rans; if(rans==x)return lans; return min(lans,rans); } } } void travel(int o){ if(!o)return; printf("%d %d\n",tr[o].l,tr[o].r); tr[o].t.travel();putchar('\n'); travel(tr[o].lc);travel(tr[o].rc); } void travel(){ travel(root); } }t; int kth(int a,int b,int k){ int l=0,r=(1e8); while(l<=r){ int mid=l+r>>1; int rank=t.rank(1,a,b,mid); if(rank>=k)r=mid-1; else{ if(t.rank(1,a,b,mid+1)>=k)return mid; else l=mid+1; } } } template<class T>void read(T &x){ static char c; static bool f; for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1; for(x=0;isdigit(c);c=getchar())x=x*10+c-'0'; if(f)x=-x; } int a[N]; int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); srand(34024902); int n,m;read(n);read(m); t.build(n); int l,r,k,opt; for(int i=1;i<=n;i++){ read(a[i]); t.insert(1,i,a[i]); } //t.travel(); while(m--){ read(opt); if(opt==1){ read(l);read(r);read(k); printf("%d\n",t.rank(1,l,r,k)+1); }else if(opt==2){ read(l);read(r);read(k); printf("%d\n",kth(l,r,k)); }else if(opt==3){ read(l);read(k); t.modify(1,l,a[l],k); a[l]=k; }else if(opt==4){ read(l);read(r);read(k); printf("%d\n",t.pre(1,l,r,k)); }else if(opt==5){ read(l);read(r);read(k); printf("%d\n",t.suc(1,l,r,k)); } } return 0; }
为了洗刷这一耻辱,我决定……
用SBT重写一遍!
然后发现,还是跑了6秒多TAT。
好慢啊。。。。。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cctype> using namespace std; const int N=50000+5; const int M=2000000+5; int lc[M],rc[M],key[M],sz[M],cnt; queue<int>q; int id(){ if(q.size()){ int t=q.front();q.pop(); return t; }else return ++cnt; } void pushup(int x){ sz[x]=sz[lc[x]]+sz[rc[x]]+1; } void lturn(int &x){ int k=rc[x];rc[x]=lc[k];lc[k]=x;sz[k]=sz[x];pushup(x);x=k; } void rturn(int &x){ int k=lc[x];lc[x]=rc[k];rc[k]=x;sz[k]=sz[x];pushup(x);x=k; } void maintain(int &x,bool flag){ if(!flag){ if(sz[lc[lc[x]]]>sz[rc[x]])rturn(x); else if(sz[rc[lc[x]]]>sz[rc[x]]){ lturn(lc[x]); rturn(x); }else return; }else{ if(sz[rc[rc[x]]]>sz[lc[x]])lturn(x); else if(sz[lc[rc[x]]]>sz[lc[x]]){ rturn(rc[x]); lturn(x); }else return; } maintain(lc[x],false);maintain(rc[x],true); maintain(x,true);maintain(x,false); } struct SBT{ int root; SBT(){ root=0; } void insert(int &x,int v){ if(!x){ key[x=id()]=v;sz[x]=1;lc[x]=rc[x]=0; } else{ sz[x]++; if(v<key[x])insert(lc[x],v); else insert(rc[x],v); maintain(x,v>=key[x]); } } void insert(int x){ insert(root,x); } int del(int &x,int v){ sz[x]--; if(key[x]==v||(v<key[x]&&!lc[x])||(v>key[x]&&!rc[x])){ int r=key[x]; if(!lc[x]||!rc[x])x=lc[x]+rc[x]; else key[x]=del(lc[x],key[x]+1); return r; }else{ if(v<key[x])return del(lc[x],v); else return del(rc[x],v); } } void modify(int x,int y){ del(root,x); insert(root,y); } int rank(int x,int k){ if(!x)return 0; if(k<=key[x])return rank(lc[x],k); else return sz[lc[x]]+1+rank(rc[x],k); } int rank(int x){ return rank(root,x); } int suc(int x,int k){ if(!x)return k; if(key[x]<=k)return suc(rc[x],k); else{ int r=suc(lc[x],k); if(r==k)return key[x]; else return r; } } int suc(int k){ return suc(root,k); } int pre(int x,int k){ if(!x)return k; if(key[x]>=k)return pre(lc[x],k); else{ int r=pre(rc[x],k); if(r==k)return key[x]; else return r; } } int pre(int k){ return pre(root,k); } void travel(int x){ if(!x)return; travel(lc[x]); printf("%d ",key[x]); travel(rc[x]); } void travel(){ travel(root); } }; struct Node{ int l,r,lc,rc; SBT t; }; struct SegmentTree{ int cnt,root; Node tr[N<<2]; SegmentTree(){ cnt=0; root=0; } void build(int &o,int l,int r){ o=++cnt; tr[o].l=l;tr[o].r=r; if(l==r)return; else{ int mid=l+r>>1; build(tr[o].lc,l,mid); build(tr[o].rc,mid+1,r); } } void build(int n){ build(root,1,n); } void insert(int o,int p,int x){ tr[o].t.insert(x); int l=tr[o].l,r=tr[o].r; if(l==r)return; else{ int mid=l+r>>1; if(p<=mid)insert(tr[o].lc,p,x); else insert(tr[o].rc,p,x); } } void modify(int o,int p,int x,int y){ //printf("%d %d\n",x,y); tr[o].t.modify(x,y); int l=tr[o].l,r=tr[o].r; if(l==r)return; else{ int mid=l+r>>1; if(p<=mid)modify(tr[o].lc,p,x,y); else modify(tr[o].rc,p,x,y); } } int rank(int o,int a,int b,int x){ int l=tr[o].l,r=tr[o].r; if(l==a&&b==r)return tr[o].t.rank(x); else{ int mid=l+r>>1; if(b<=mid)return rank(tr[o].lc,a,b,x); else if(mid<a)return rank(tr[o].rc,a,b,x); else return rank(tr[o].lc,a,mid,x)+rank(tr[o].rc,mid+1,b,x); } } int pre(int o,int a,int b,int x){ int l=tr[o].l,r=tr[o].r; if(l==a&&b==r)return tr[o].t.pre(x); else{ int mid=l+r>>1; if(b<=mid)return pre(tr[o].lc,a,b,x); else if(mid<a)return pre(tr[o].rc,a,b,x); else{ int lans=pre(tr[o].lc,a,mid,x),rans=pre(tr[o].rc,mid+1,b,x); if(lans==x)return rans; if(rans==x)return lans; return max(lans,rans); } } } int suc(int o,int a,int b,int x){ int l=tr[o].l,r=tr[o].r; if(l==a&&b==r)return tr[o].t.suc(x); else{ int mid=l+r>>1; if(b<=mid)return suc(tr[o].lc,a,b,x); else if(mid<a)return suc(tr[o].rc,a,b,x); else{ int lans=suc(tr[o].lc,a,mid,x),rans=suc(tr[o].rc,mid+1,b,x); if(lans==x)return rans; if(rans==x)return lans; return min(lans,rans); } } } void travel(int o){ if(!o)return; printf("%d %d\n",tr[o].l,tr[o].r); tr[o].t.travel();putchar('\n'); travel(tr[o].lc);travel(tr[o].rc); } void travel(){ travel(root); } }t; int kth(int a,int b,int k){ int l=0,r=(1e8); while(l<=r){ int mid=l+r>>1; int rank=t.rank(1,a,b,mid); if(rank>=k)r=mid-1; else{ if(t.rank(1,a,b,mid+1)>=k)return mid; else l=mid+1; } } } template<class T>void read(T &x){ static char c; static bool f; for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1; for(x=0;isdigit(c);c=getchar())x=x*10+c-'0'; if(f)x=-x; } int a[N]; int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); int n,m;read(n);read(m); t.build(n); int l,r,k,opt; for(int i=1;i<=n;i++){ read(a[i]); t.insert(1,i,a[i]); } //t.travel(); while(m--){ read(opt); if(opt==1){ read(l);read(r);read(k); printf("%d\n",t.rank(1,l,r,k)+1); }else if(opt==2){ read(l);read(r);read(k); printf("%d\n",kth(l,r,k)); }else if(opt==3){ read(l);read(k); t.modify(1,l,a[l],k); a[l]=k; }else if(opt==4){ read(l);read(r);read(k); printf("%d\n",t.pre(1,l,r,k)); }else if(opt==5){ read(l);read(r);read(k); printf("%d\n",t.suc(1,l,r,k)); } } return 0; }