标签:
思博题加强版,还是思博题,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