题目大意:
两种操作
0:对一个点反色(白变黑,黑变白)
1:查询这个点到一号点这一条链上离一号点最近的黑点的编号
我没话说了……这道题我交了可能有几十次,调了两个多小时,和别人对拍,就是不知道哪里写错了……
最后逼得没办法重新写了一遍……AC……
蛋疼的SPOJ……
#include<cstdio> #define rep(i,a,b) for(int i=a,tt=b;i<=tt;++i) #define erep(i,e,x) for(int i=x;i;i=e[i].next) const int oo=1000000000,maxn=100008,maxm=maxn<<1; int n,m; int h[maxn],vis[maxn],d[maxn],col[maxn],q[maxn]; struct E { int next,node; }e[maxm]; struct T { int lc,rc,fa,val,key,idx; T(){val=key=oo;lc=rc=fa=idx=0;} #define lc(x) tree[x].lc #define rc(x) tree[x].rc #define fa(x) tree[x].fa #define val(x) tree[x].val #define key(x) tree[x].key #define idx(x) tree[x].idx }tree[maxn]; void add(int a,int b){static int tot=0;e[++tot].next=h[a];e[tot].node=b;h[a]=tot;} void Update(int x) { if(val(lc(x))<val(rc(x)))val(x)=val(lc(x)),idx(x)=idx(lc(x)); else val(x)=val(rc(x)),idx(x)=idx(rc(x)); if(key(x)<val(x))val(x)=key(x),idx(x)=x; } void Zig(int x) { int y=fa(x),z=fa(y); if(lc(z)==y)lc(z)=x;else if(rc(z)==y)rc(z)=x;fa(x)=z; fa(rc(x))=y;lc(y)=rc(x);rc(x)=y;fa(y)=x; Update(y); } void Zag(int x) { int y=fa(x),z=fa(y); if(lc(z)==y)lc(z)=x;else if(rc(z)==y)rc(z)=x;fa(x)=z; fa(lc(x))=y;rc(y)=lc(x);lc(x)=y;fa(y)=x; Update(y); } bool isRoot(int x){return lc(fa(x))!=x&&rc(fa(x))!=x;} void Splay(int x) { for(int y,z;!isRoot(x);) { y=fa(x);z=fa(y); if(isRoot(y)) if(lc(y)==x)Zig(x); else Zag(x); else if(lc(z)==y) if(lc(y)==x)Zig(y),Zig(x); else Zag(x),Zig(x); else if(rc(y)==x)Zag(y),Zag(x); else Zig(x),Zag(x); } Update(x); } void Expose(int x){for(int y=0;x;x=fa(x)){Splay(x);rc(x)=y;Update(x);y=x;}} void Build() { int l=1,r=1,x,y; q[l]=1;vis[1]=true; while(l<=r) { x=q[l++]; erep(i,e,h[x]) { y=e[i].node;if(vis[y])continue; vis[y]=true;q[++r]=y; fa(y)=x;idx(y)=y;d[y]=d[x]+1; } } } int main() { scanf("%d%d",&n,&m);int a,b; rep(i,1,n-1)scanf("%d%d",&a,&b),add(a,b),add(b,a); Build(); rep(i,1,m) { scanf("%d%d",&a,&b); if(a) { Expose(b);Splay(b); printf("%d\n",val(b)>=oo?-1:idx(b)); } else { Splay(b); if(col[b])col[b]=0,key(b)=oo; else col[b]=1,key(b)=d[b]; Update(b); } } return 0; }