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

来源:互联网 发布:windows隐藏文件夹 编辑:程序博客网 时间:2024/06/05 18:02

裸的可持久化值域线段树+启发式(贪心又暴力地)合并

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

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

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

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


#include<bits/stdc++.h>#define MAXN 80057#define MAX2 20000057using 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);elseinsert(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);elsereturn 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;}


0 0
原创粉丝点击