森林
来源:互联网 发布:半包合同知乎 编辑:程序博客网 时间:2024/04/27 20:10
森林
题目描述:贴个传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3123
题解
用主席树维护区间k小。对于每个节点,以父亲节点为上一版本。
对于每次加边,进行启发式合并,暴力搜索子树内每几个节点,重构主席树即可。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<algorithm>#define N 80005#define P 17using namespace std;int cyc,n,m,Q,cnt,pre,s[N],Tnum,num[N];int w[N][P+1],rt[N],flag[N],dep[N];int k,la[N],ff[N*2],fa[N],size[N];struct node{int a,b;}map[N*2];struct point{int lc,rc,size;}t[N*300];int get(int x){return x^pre;}void add(int a,int b){ map[++k]=(node){a,b};ff[k]=la[a];la[a]=k; map[++k]=(node){b,a};ff[k]=la[b];la[b]=k;}class func_seg_tree{ public: void modify(int &x,int pre,int l,int r,int des) { t[x=++cnt]=t[pre];t[x].size++; if(l==r)return; int mid=l+r>>1; if(des<=mid)modify(t[x].lc,t[pre].lc,l,mid,des); else modify(t[x].rc,t[pre].rc,mid+1,r,des); } int qry(int a,int b,int c,int d,int l,int r,int k) { if(l==r)return num[l]; int A=t[t[a].lc].size,B=t[t[b].lc].size; int C=t[t[c].lc].size,D=t[t[d].lc].size; int sum=A+B-C-D,mid=l+r>>1; if(k<=sum)return qry(t[a].lc,t[b].lc,t[c].lc,t[d].lc,l,mid,k); return qry(t[a].rc,t[b].rc,t[c].rc,t[d].rc,mid+1,r,k-sum); } }T;void dfs(int x){ flag[x]=1;size[x]=1; T.modify(rt[x],rt[w[x][0]],1,Tnum,s[x]); for(int i=1;i<=P;i++) w[x][i]=w[w[x][i-1]][i-1]; for(int a=la[x];a;a=ff[a]) if(!flag[map[a].b]) { w[map[a].b][0]=x;dep[map[a].b]=dep[x]+1; dfs(map[a].b);size[x]+=size[map[a].b]; } flag[x]=0;}int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=P;i>=0;i--) if(dep[w[x][i]]>=dep[y])x=w[x][i]; if(x==y)return x; for(int i=P;i>=0;i--) if(w[x][i]!=w[y][i])x=w[x][i],y=w[y][i]; return w[x][0];}int find(int x){ if(!fa[x])return x; return fa[x]=find(fa[x]);}int main(){ int a,b,x,y,z,pos,X,Y;char ch; scanf("%d%d%d%d",&cyc,&n,&m,&Q); for(int i=1;i<=n;i++) scanf("%d",&s[i]),num[i]=s[i]; sort(num+1,num+n+1); Tnum=unique(num+1,num+n+1)-num-1; for(int i=1;i<=n;i++) s[i]=lower_bound(num+1,num+Tnum+1,s[i])-num; for(int i=1;i<=m;i++) scanf("%d%d",&a,&b),add(a,b); for(int i=1;i<=n;i++)if(!w[i][0])dep[i]=1,dfs(i); while(Q--) { scanf(" %c%d%d",&ch,&x,&y); x=get(x);y=get(y); if(ch=='Q') { scanf("%d",&z);z=get(z);pos=lca(x,y); printf("%d\n",pre=T.qry(rt[x],rt[y],rt[pos],rt[w[pos][0]],1,Tnum,z)); } else { int X=find(x),Y=find(y); if(size[X]>size[Y])swap(x,y); w[x][0]=y;dep[x]=dep[y]+1; dfs(x);add(x,y); } } return 0;}
0 0
- 森林
- 森林
- 《重庆森林》
- 纯粹森林
- 孔雀森林
- 森林大会
- 挪威森林
- 筷子 、森林
- 森林冒险
- 互联网森林?
- 随机森林
- 随机森林
- 随机森林
- 随机森林
- 随机森林
- 随机森林
- 随机森林
- 随机森林
- 大数加法
- 《Linux操作系统分析》之分析精简的Linux的内核中断和时间片轮询
- 连接查询 两张表里有同名字段的问题
- 七牛云图片处理实践之GIF|如何解决GIF流量爆炸问题?
- HDU 2816 I Love You Too [Ad Hoc]
- 森林
- Linux多线程编程的时候如何查看一个进程中的某个线程是否存活
- 素数求和问题
- POJ1077Eight
- HelloWorld版的SpringMVC使用注解驱动的依赖注入
- UVA 10054 The Necklace(欧拉回路)
- #include<sys/types.h>
- Android ViewPager 垂直滑动 纵向滑动 VerticalViewPager
- 解压GZIP加密后的Response