BZOJ 3123: [Sdoi2013]森林【可持久化值域线段树+启发式合并
2016-07-28 23:33
483 查看
裸的可持久化值域线段树+启发式(贪心又暴力地)合并
……合并的时候忘记修改深度了……不知道为什么现在稍微长一点的代码就不想调了【好颓啊QwQ
没什么好说的,一切都是套路……
求第k大/第k小很明显满足加减的性质于是
要求链上的值 其实只用记录每个节点到根的数据……然后进行加加减减【根本不用链剖【神犇们说倍增LCA太丑于是都去学LCT求LCA了我就…………跪着
……合并的时候忘记修改深度了……不知道为什么现在稍微长一点的代码就不想调了【好颓啊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; }
相关文章推荐
- 视频播放遇到的坑(新手)
- IOS学习之核心动画-粒子效果
- Codeforces Round #268 (Div. 1)A. 24 Game
- JVM工具jmap、jconsole、jstack、jstat、Javap检测内存泄漏问题
- Linux命令之 file命令
- copy 和 MutableCopy
- Codeforces Round #268 (Div. 1)A. 24 Game
- App上架流程
- spring boot thymeleaf 入门 demo
- Android高性能高斯模糊方案
- 栈帧分析
- openwrt 添加自定义内核模块
- fragment的使用以及fragment大家族解析
- ggplot
- mac 查看pid
- ACM Steps 2.1.8
- DESCryptoServiceProvider
- Java中只有按值传递,没有按引用传递!
- 程序猿如何预估工时之二
- u-boot-2016.05移植:(1)、建立新板并配置,使能正常编译通过