小z有一片森林,含有 N N N 个节点,每个节点上都有一个非负整数作为权值。 初始的时候,森林中有 M M M 条边。
小z希望执行 T T T 个操作,操作有两类:
-
Q x y k Q~x~y~k Q x y k 查询点 x x x 到点 y y y 路径上所有的权值中,第 k k k 小的权值是多少。此操作保证点 x x x 和点 y y y 连通,同时这两个节点的路径上至少有 k k k 个点
-
L x y L~x~y L x y 在点 x x x 和点 y y y 之间连接一条边。保证完成此操作后,仍然是一片森 林。
为了体现程序的在线性,我们把输入数据进行了加密。设 l a s t a n s lastans lastans 为程序上 一次输出的结果,初始的时候 l a s t a n s lastans lastans 为 0 0 0。
对于一个输入的操作 Q x y k Q~x~y~k Q x y k ,其真实操作为 Q x ⊕ l a s t a n s y ⊕ l a s t a n s k ⊕ l a s t a n s Q~x \oplus lastans~y \oplus lastans~k \oplus lastans Q x⊕lastans y⊕lastans k⊕lastans
对于一个输入的操作 L x y L~x~y L x y ,其真实操作为 L x ⊕ l a s t a n s y ⊕ l a s t a n s L~x \oplus lastans~ y \oplus lastans L x⊕lastans y⊕lastans 。
其中 ⊕ \oplus ⊕ 运算符表示异或。 请写一个程序来帮助小z完成这些操作。
第一行包含一个正整数 t e s t c a s e testcase testcase,表示当前测试数据的测试点编号。保证 1 ≤ t e s t c a s e ≤ 20 1 \le testcase \le 20 1≤testcase≤20
第二行包含三个整数 N , M , T N,M,T N,M,T,分别表示节点数、初始边数、操作数。
第三行包含 N N N 个非负整数表示 N N N 个节点上的权值。
接下来 M M M 行,每行包含两个整数 x x x 和 y y y ,表示初始的时候,点 x x x 和点 y y y 之 间有一条无向边。
接下来 T T T行,每行描述一个操作,格式为“ Q x y k Q~ x~y~k~ Q x y k ”或者“ L x y L~x~ y L x y",其含义 见题目描述部分。
对于每一个第一类操作,输出一个非负整数表示答案。
样例输入
1
8 4 8
1 1 2 2 3 3 4 4
4 7
1 8
2 4
2 1
Q 8 7 3
Q 3 5 1
Q 10 0 0
L 5 4
L 3 2
L 0 7
Q 9 2 5
Q 6 1 6
样例输出
2
2
1
4
2
sdoi2013
题解:
考虑若不连边,那么树上主席树直接跑。但是连边就很麻烦。于是考虑启发式合并,每次暴力重构
#include<bits/stdc++.h>
#define N 80004
using namespace std;
/*inline int read(){
int x=0;char s=getchar();
while(s<'0'||s>'9')s=getchar();
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
return x;
}*/
int btot,head[N],ver[N<<1],nex[N<<1];
inline void add(int x,int y){
nex[++btot]=head[x];head[x]=btot;ver[btot]=y;
}
int a[N],b[N],bt,root[N],f[N][21],dep[N],TT=20,fa[N],size[N];
struct seg{
int ls,rs,sum;
}t[10000007];
int tot;
int change(int p,int q,int l,int r,int tl,int val){
t[p]=t[q];
if(l==r){
t[p].sum+=val;
return p;
}
int mid=(l+r)>>1;
if(tl<=mid)t[p].ls=change(++tot,t[q].ls,l,mid,tl,val);
else t[p].rs=change(++tot,t[q].rs,mid+1,r,tl,val);
t[p].sum=t[t[p].ls].sum+t[t[p].rs].sum;
return p;
}
int ask(int p1,int p2,int q1,int q2,int l,int r,int kk){
if(l==r)return l;
int mid=(l+r)>>1,sum=t[t[q1].ls].sum+t[t[q2].ls].sum-t[t[p1].ls].sum-t[t[p2].ls].sum;
if(sum<kk)return ask(t[p1].rs,t[p2].rs,t[q1].rs,t[q2].rs,mid+1,r,kk-sum);
else return ask(t[p1].ls,t[p2].ls,t[q1].ls,t[q2].ls,l,mid,kk);
}
inline void init(){
tot=0;btot=0;bt=0;t[0].ls=t[0].rs=t[0].sum=0;
memset(head,0,sizeof(head));
//memset(f,0,sizeof(f));
//memset(dep,0,sizeof(dep));
}
inline void test(int p,int l,int r){
cout<<l<<" "<<r<<":"<<t[p].sum<<endl;
int mid=(l+r)>>1;
if(l==r||!p)return ;
test(t[p].ls,l,mid);test(t[p].rs,mid+1,r);
}
void dfs(int x,int las){
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==las)continue;
f[y][0]=x;dep[y]=dep[x]+1;
for(int j=1;j<=TT;++j)f[y][j]=f[f[y][j-1]][j-1];
root[y]=change(++tot,root[x],1,bt,a[y],1);
dfs(y,x);
}
}
inline int get(int x){
if(fa[x]==x)return x;
return fa[x]=get(fa[x]);
}
void dfs2(int x,int las){
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==las)continue;
f[y][0]=x;dep[y]=dep[x]+1;
fa[y]=x;size[get(y)]++;
for(int j=1;j<=TT;++j)f[y][j]=f[f[y][j-1]][j-1];
root[y]=change(++tot,root[x],1,bt,a[y],1);
dfs2(y,x);
}
}
inline int get_lca(int x,int y){
if(dep[x]>dep[y])swap(x,y);
for(int i=TT;i+1;--i)if(dep[f[y][i]]>=dep[x])y=f[y][i];
if(x==y)return x;
for(int i=TT;i+1;--i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[x][0];
}
inline int num(int x){
return lower_bound(b+1,b+1+bt,x)-b;}
inline void test(int n){
for(int i=1;i<=n;++i){
for(int j=0;j<=2;++j){
cout<<i<<" "<<j<<" "<<f[i][j]<<endl;
}
}
}
int main(){
// freopen("P3302_2.in","r",stdin);
// freopen("test.out","w",stdout);
int T;
while(scanf("%d",&T)!=EOF){
init();
// cout<<T<<endl;
int n,m,t;scanf("%d%d%d",&n,&m,&t);
// cout<<n<<" "<<m<<" "<<t<<endl;
for(int i=1;i<=n;++i)scanf("%d",&a[i]),b[++bt]=a[i];
for(int i=1;i<=n;++i)fa[i]=i,size[i]=1;
for(int i=1;i<=m;++i){
int x,y;scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
sort(b+1,b+1+bt);bt=unique(b+1,b+1+bt)-b-1;
for(int i=1;i<=n;++i)a[i]=num(a[i]);
int lans=0;
for(int i=1;i<=n;++i){
if(!dep[i]){
root[i]=change(++tot,root[0],1,bt,a[i],1);
dep[i]=1;
dfs2(i,0);
}
}
for(int i=1;i<=t;++i){
char c[3];scanf("%s",c);
if(c[0]=='L'){
int x,y,fx,fy;
scanf("%d%d",&x,&y);
x^=lans,y^=lans;
fx=get(x),fy=get(y);
if(size[fx]<size[fy])swap(x,y),swap(fx,fy);
//cout<<x<<" "<<y<<" "<<fx<<" "<<fy<<endl;
//cout<<size[fx]<<" "<<size[fy]<<endl;
fa[fy]=fx;size[fx]+=size[fy];
add(x,y);add(y,x);
root[y]=change(++tot,root[x],1,bt,a[y],1);
dep[y]=dep[x]+1;f[y][0]=x;
for(int j=1;j<=TT;++j)f[y][j]=f[f[y][j-1]][j-1];
dfs(y,x);
}else{
int x,y,k,lca;
scanf("%d%d%d",&x,&y,&k);x^=lans,y^=lans,k^=lans;lca=get_lca(x,y);
//cout<<x<<" "<<y<<" "<<k<<" "<<lca<<endl;
lans=ask(root[f[lca][0]],root[lca],root[x],root[y],1,bt,k);
lans=b[lans];
printf("%d\n",lans);
}
//cout<<"-1"<<endl;
}
//test(n);
}
return 0;
}
/*
1
8 4 8
1 1 2 2 3 3 4 4
4 7
1 8
2 4
2 1
Q 8 7 3
Q 3 5 1
Q 10 0 0
L 5 4
L 3 2
L 0 7
Q 9 2 5
Q 6 1 6
*/