您的位置:首页 > 其它

BZOJ 3123: [Sdoi2013]森林【可持久化值域线段树+启发式合并

2016-07-28 23:33 483 查看
裸的可持久化值域线段树+启发式(贪心又暴力地)合并

……合并的时候忘记修改深度了……不知道为什么现在稍微长一点的代码就不想调了【好颓啊QwQ

没什么好说的,一切都是套路……

求第k大/第k小很明显满足加减的性质于是

要求链上的值 其实只用记录每个节点到根的数据……然后进行加加减减【根本不用链剖【神犇们说倍增LCA太丑于是都去学LCT求LCA了我就…………跪着

#include<bits/stdc++.h>
#define MAXN 80057
#define MAX2 20000057
using namespace std;	int n,m,t;
int MX;

int cnt[MAX2],cnt_node=0;
int leftson[MAX2],rightson[MAX2];

void insert(int pre,int &now,int l,int r,int key){
cnt[++cnt_node]=cnt[now];
now=cnt_node;
++cnt[now];
if(l==r)	return ;
int mid=(l+r)>>1;
leftson[now]=leftson[pre] , rightson[now]=rightson[pre];
if(key<=mid)	insert(leftson[pre],leftson[now],l,mid,key);
else	insert(rightson[pre],rightson[now],mid+1,r,key);
}

int inqry(int r1,int r2,int r3,int r4,		int l,int r,int k){
if(l==r)	return l;
int mid=(l+r)>>1;
int dt_l=cnt[leftson[r1]]+cnt[leftson[r2]]
-cnt[leftson[r3]]-cnt[leftson[r4]];
if(k<=dt_l)	return inqry(leftson[r1],leftson[r2],leftson[r3],leftson[r4],l,mid,k);
else	return inqry(rightson[r1],rightson[r2],rightson[r3],rightson[r4],mid+1,r,k-dt_l);
}

//=================================================
struct t1{
int to,nxt;
}edge[MAXN<<1];	int cnt_edge=0;
int fst[MAXN];
void addedge(int x,int y){
edge[++cnt_edge].to=y;
edge[cnt_edge].nxt=fst[x];
fst[x]=cnt_edge;
}
int rec[MAXN];

int root[MAXN];

int anc[MAXN][17];
void jump(int now){
for(int i=1;i<17;++i)
anc[now][i]=anc[ anc[now][i-1] ][i-1];
}

int root_num[MAXN],siz[MAXN],dpt[MAXN];
void dfs(int now){
siz[now]=1;
jump(now);
insert(root[ anc[now][0] ],root[now],1,MX,rec[now]);
for(int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
if(edge[tmp].to==anc[now][0])	continue;
int ch=edge[tmp].to;
anc[ch][0]=now;
root_num[ch]=root_num[now];
dpt[ch]=dpt[now]+1;

dfs(ch);
siz[now]+=siz[ch];
}
}

int lca(int x,int y){
if(dpt[x]<dpt[y])	swap(x,y);
int dlt=dpt[x]-dpt[y];
for(int i=16;~i;--i)
if(dlt&(1<<i))	x=anc[x][i];
if(x==y)	return x;
for(int i=16;~i;--i){
if(anc[x][i]!=anc[y][i])
x=anc[x][i], y=anc[y][i];
}
if(x==y)	return x;
return anc[x][0];
}

//============================================================
int work_Q(int x,int y,int k){
int LCA=lca(x,y);
int F_lca=anc[LCA][0];
return inqry(root[x],root[y],root[LCA],root[ anc[LCA][0] ],1,MX,k);
}

void work_L(int x,int y){
addedge(x,y),addedge(y,x);
anc[y][0]=x;
siz[root_num[x]]+=siz[root_num[y]];
root_num[y]=root_num[x];
dpt[y]=dpt[x]+1;
dfs(y);
}

char opt[5];
int read_x,read_y,read_k;
int lastans=0;
int main(){
scanf("%*d%d%d%d",&n,&m,&t);
for(int i=1;i<=n;++i)	scanf("%d",rec+i),MX=max(MX,rec[i]);
for(int i=1;i<=m;++i)
scanf("%d%d",&read_x,&read_y),
addedge(read_x,read_y), addedge(read_y,read_x);

for(int i=1;i<=n;++i)
if(!root_num[i])
root_num[i]=i,dpt[i]=1, dfs(i);

while(t--){
scanf("%s",opt);
if(opt[0]=='Q'){
scanf("%d%d%d",&read_x,&read_y,&read_k);
read_x^=lastans,read_y^=lastans,read_k^=lastans;
printf("%d\n",lastans=work_Q(read_x,read_y,read_k));
}
else{
scanf("%d%d",&read_x,&read_y);
read_x^=lastans,read_y^=lastans;
if(siz[root_num[read_x]]<siz[root_num[read_y]])	swap(read_x,read_y);
work_L(read_x,read_y);
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: