[bzoj3600]没有人的算术
来自FallDream的博客,未经允许,请勿转载,谢谢。
考虑用一个实数来表示大小关系。维护两个平衡树,一棵splay来维护区间,然后一个替罪羊来维护每个数的标号。
插入一种数的时候,可以取它的前驱后继的平均值。然后替罪羊重建的时候正好吧数字重新标号即可。
#include<iostream> #include<cstdio> #define MN 500000 #define ld long double #define INF (ld)1e99 using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } namespace SGT { ld s[MN+5];int A[MN+5],B[MN+5],rt,fa[MN+5],cnt=0,c[MN+5][2],mark=0,q[MN+5],size[MN+5],top; int GetID(int&x,int a,int b,ld lt,ld rt,int last=0) { if(!x){ x=++cnt;A[x]=a;B[x]=b; s[x]=(lt+rt)/2.0;fa[x]=last;size[x]=1; return cnt; } if(x!=2&&A[x]==a&&B[x]==b) return x; int res; if(x==2||((s[A[x]]==s[a]&&s[B[x]]<s[b])||s[A[x]]<s[a])) res=GetID(c[x][1],a,b,s[x],rt,x); else res=GetID(c[x][0],a,b,lt,s[x],x); size[x]=size[c[x][0]]+size[c[x][1]]+1; if(max(size[c[x][0]],size[c[x][1]])>0.75*size[x]) mark=x; return res; } void ins(int&x,int a,int b,ld ci,int last=0) { if(!x){ x=++cnt;s[x]=ci; A[x]=a;B[x]=b;fa[x]=last; return; } if((s[A[x]]==s[a]&&s[B[x]]<s[b])||s[A[x]]<s[a]) ins(c[x][1],a,b,ci,x); else ins(c[x][0],a,b,ci,x); size[x]=size[c[x][0]]+size[c[x][1]]+1; } void Dfs(int x) { if(c[x][0]) Dfs(c[x][0]); q[++top]=x; if(c[x][1]) Dfs(c[x][1]); } void build(int&x,int l,int r,ld lt,ld rt,int last) { if(l>r){x=0;return;} int mid=l+r>>1;x=q[mid];s[x]=(lt+rt)/2.0;fa[x]=last; build(c[x][0],l,mid-1,lt,s[x],x); build(c[x][1],mid+1,r,s[x],rt,x); size[x]=size[c[x][0]]+size[c[x][1]]+1; } void rebuild() { top=0;Dfs(mark);int y=fa[mark]; if(!y) build(rt,1,top,s[q[1]],s[q[top]],0); else build(c[y][c[y][1]==mark],1,top,s[q[1]],s[q[top]],y); mark=0; } } struct Data{int x,from; friend Data operator+(Data a,Data b) { if(SGT::s[a.x]==SGT::s[b.x]) return (Data){a.x,min(a.from,b.from)}; if(SGT::s[a.x]>SGT::s[b.x]) return a; else return b; } }s[MN+5]; struct data{ld a,b,x; bool operator <(const data&y)const{return a==y.a?b<y.b:a<y.a;} }; int n,m,fa[MN+5],c[MN+5][2],mark,rt=0,num[MN+5]; void update(int x) { s[x]=(Data){num[x-1],x-1}; if(c[x][0]) s[x]=s[x]+s[c[x][0]]; if(c[x][1]) s[x]=s[x]+s[c[x][1]]; } void rotate(int x,int&k) { int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; if(y==k) k=x; else c[z][c[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; update(y);update(x); } void splay(int x,int&k) { for(;x!=k;rotate(x,k)) if(fa[x]!=k) rotate((c[fa[fa[x]]][1]==fa[x]^c[fa[x]][1]==x)?x:fa[x],k); } int Split(int l,int r) { splay(l,rt); splay(r+2,c[rt][1]); return c[c[rt][1]][0]; } void Modify(int x,int k) { if(x!=k) Modify(c[x][k>x],k); update(x); } void build(int&x,int l,int r,int last) { if(l>r){x=0;return;} int mid=l+r>>1;x=mid;fa[x]=last; build(c[x][0],l,mid-1,x); build(c[x][1],mid+1,r,x); update(x); } char op[10]; int main() { n=read();m=read(); SGT::cnt=1;SGT::s[0]=-1;SGT::s[1]=INF; SGT::ins(SGT::rt,0,0,0);SGT::ins(SGT::rt,1,1,INF); for(int i=1;i<=n+2;++i) num[i]=0; build(rt,1,n+2,0); for(int i=1;i<=m;++i) { scanf("%s",op+1); if(op[1]=='C') { int a=read(),b=read(),k=read(); num[k]=SGT::GetID(SGT::rt,num[a],num[b],0,INF); if(SGT::mark) SGT::rebuild(); Modify(rt,k+1);splay(k+1,rt); } else { int l=read(),r=read(); int x=Split(l,r); printf("%d\n",s[x].from); } } return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream