BZOJ 3123 [Sdoi2013]森林
题解:
启发式合并主席树
时间复杂度O(nlogn*logn)
空间复杂度O(nlogn*logn)
Woc初始的时候也用了启发式合并建图,然后RE成翔了
一开始算错了空间,下次注意
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int maxn=100000;
int n,m,TT;
int a[maxn];
int lastans=0;
int cntedge=0;
int head[maxn]={0};
int to[maxn<<1]={0},nex[maxn<<1]={0};
void Addedge(int x,int y){
nex[++cntedge]=head[x];
to[cntedge]=y;
head[x]=cntedge;
}
int b[maxn],nn;
struct PresidentTree{
int ls,rs,d;
}tree[maxn*100];
int Tsize=0;
int root[maxn]={0};
void BuildTree(int &now,int l,int r){
now=++Tsize;
tree[now].d=0;
if(l==r)return;
int mid=(l+r)>>1;
BuildTree(tree[now].ls,l,mid);
BuildTree(tree[now].rs,mid+1,r);
}
void Updatapoint(int &now,int l,int r,int pre,int p){
now=++Tsize;
tree[now]=tree[pre];
tree[now].d++;
if(l==r)return;
int mid=(l+r)>>1;
if(p<=mid)Updatapoint(tree[now].ls,l,mid,tree[pre].ls,p);
else Updatapoint(tree[now].rs,mid+1,r,tree[pre].rs,p);
}
int Queryans(int l,int r,int x,int y,int z,int t,int k){
if(l==r)return b[l];
int lx=tree[x].ls,ly=tree[y].ls,lz=tree[z].ls,lt=tree[t].ls;
int d=tree[lx].d+tree[ly].d-tree[lz].d-tree[lt].d;
int mid=(l+r)>>1;
if(k<=d)return Queryans(l,mid,lx,ly,lz,lt,k);
else return Queryans(mid+1,r,tree[x].rs,tree[y].rs,tree[z].rs,tree[t].rs,k-d);
}
int f[maxn][20];
int dep[maxn];
void Dfs(int x,int fa){
dep[x]=dep[fa]+1;
f[x][0]=fa;
for(int j=1;j<=19;++j){
f[x][j]=f[f[x][j-1]][j-1];
}
Updatapoint(root[x],1,nn,root[fa],a[x]);
for(int i=head[x];i;i=nex[i]){
if(to[i]==fa)continue;
Dfs(to[i],x);
}
}
int Getlca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
for(int j=19;j>=0;--j){
if(dep[f[u][j]]>=dep[v]){
u=f[u][j];
}
}
if(u==v)return u;
for(int j=19;j>=0;--j){
if(f[u][j]!=f[v][j]){
u=f[u][j];v=f[v][j];
}
}
return f[u][0];
}
int Getans(int u,int v,int k){
int lca=Getlca(u,v);
return Queryans(1,nn,root[u],root[v],root[lca],root[f[lca][0]],k);
}
int father[maxn];
int siz[maxn];
int Getf(int x){
if(father[x]==x)return x;
return father[x]=Getf(father[x]);
}
void Unionn(int x,int y){
int fx=Getf(x);
int fy=Getf(y);
siz[fy]+=siz[fx];
father[fx]=fy;
}
int testcase;
int main(){
scanf("%d",&testcase);
scanf("%d%d%d",&n,&m,&TT);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
nn=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;++i)a[i]=lower_bound(b+1,b+1+nn,a[i])-b;
BuildTree(root[0],1,nn);
for(int i=1;i<=n;++i){
father[i]=i;siz[i]=1;
}
while(m--){
int x,y;
scanf("%d%d",&x,&y);
Addedge(x,y);
Addedge(y,x);
Unionn(x,y);
}
for(int i=1;i<=n;++i){
if(!root[i])Dfs(i,0);
}
while(TT--){
char opty=getchar();
while(opty!='Q'&&opty!='L')opty=getchar();
int x,y,z;
scanf("%d%d",&x,&y);
x^=lastans;y^=lastans;
if(opty=='Q'){
scanf("%d",&z);
z^=lastans;
printf("%d\n",lastans=Getans(x,y,z));
}else{
int fx=Getf(x);
int fy=Getf(y);
Addedge(x,y);
Addedge(y,x);
if(Getf(x)==Getf(y))exit(0);
if(siz[fx]<siz[fy]){
Dfs(x,y);
}else{
Dfs(y,x);
}
Unionn(x,y);
}
}
return 0;
}
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!

浙公网安备 33010602011771号