标签:
思博题加强版,还是思博题,RT,没了。
内存log^2,写了回收的话可以少个log。
lca不能用树剖了好悲伤(IoI),讨厌倍增。
没有1A好不爽啊啊啊,最近写思博题只有一道1A的是要退役的节奏(@_@)
#include<cstdio> #include<algorithm> #define N 80005 #define M (l+r>>1) using namespace std; char o[2]; int k,m,q,s,t,u,v,x,y; struct node{ node* c[2]; int s; }c[N*300],*next=c+1; node* f[N]; int query(int k,node* s, node* t,node* u,node* v){ int i,j,r=m,l=1; while(l!=r){ j=s->s+t->s -u->s-v->s; i=k>j,k-=i*j; s=s->c[i]; t=t->c[i]; u=u->c[i]; v=v->c[i]; i?l=M+1:r=M; } return l; } void add(int v,node* s, node** t){ int i,r=m,l=1; while(l!=r){ *t=next++; **t=*s,i=v>M; (*t)->s+=i^1; s=s->c[i]; t=&(*t)->c[i]; i?l=M+1:r=M; } } struct edge{ edge* s; int v; }e[N*2],*back=e,*h[N]; void add(int u,int v){ h[u]=&(*back++ =(edge){h[u],v}); h[v]=&(*back++ =(edge){h[v],u}); } typedef int ds[N]; ds a[16+1],&p=*a,d,r,z,l; void dfs(int u){ add(l[u],f[p[u]],f+u); r[u]=1; d[u]=d[p[u]]+1; for(int j=0;j!=16;++j) a[j+1][u] =a[j][a[j][u]]; for(edge* i=h[u];i;i=i->s) if(i->v!=p[u]){ p[i->v]=u; dfs(i->v); r[u]+=r[i->v]; } } int lca(int s,int t){ if(d[s]<d[t]) swap(s,t); for(int j=0;d[s] ^d[t];++j) s=d[s]-d[t]&1<<j ?a[j][s]:s; for(int j=16;~j;--j) if(a[j][s]^a[j][t]){ s=a[j][s]; t=a[j][t]; } return s^t?p[s]:s; } int find(int s){ for(int j=16;~j;--j) if(a[j][s]) s=a[j][s]; return s; } int main(){ *f=&(*c=(node){c,c}); scanf("%*d%d%d%d", &m,&x,&y); for(int i=1;i<=m;++i){ scanf("%d",l+i); z[i]=l[i]; } sort(z+1,z+m+1); for(int i=1;i<=m;++i) l[i]=lower_bound( z+1,z+m+1,l[i])-z; while(x--){ scanf("%d%d",&s,&t); add(s,t); } for(int i=1;i<=m;++i) if(!d[i]) dfs(i); while(y--){ scanf("%s%d%d",o,&s,&t); s^=q,t^=q; if(*o==‘L‘){ add(s,t); u=find(s),v=find(t); if(r[u]<r[v]){ r[v]+=r[u]; p[s]=t,dfs(s); }else{ r[u]+=r[v]; p[t]=s,dfs(t); } }else{ scanf("%d",&k); u=lca(s,t); printf("%d\n",q=z[ query(k^q,f[s], f[t],f[u],f[p[u]])]); } } }
bzoj3123: [Sdoi2013]森林 主席树+启发式合并
标签:
原文地址:http://www.cnblogs.com/f321dd/p/5697723.html