jzoj 5012. 【NOI2017模拟3.13】远行 启发式合并
来源:互联网 发布:微信链接网络出错1003 编辑:程序博客网 时间:2024/04/29 18:11
题意
给n个点,要求资瓷q个操作:
1 x y表示在x到y之间连一条边
2 x表示求x到其能到达的最远的点的距离
满足任意时刻该图为一片森林。
分析
显然每个点能到的最远的点为该点所在树的直径的其中一个端点,那么我们只要维护树的直径即可。
若两棵树合并,那么新直径的两个端点必然是两棵树的旧直径的端点,维护起来就十分的爽。
但是距离要怎么求呢?
一开始想的是用lct来维护,正解貌似也是lct,但是由于其码量和常数都十分巨大,蒟蒻看得瑟瑟发抖,于是就打了启发式合并。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 300005using namespace std;int n,q,last[N],fa[N][20],dep[N],f[N],size[N],cnt;struct weight{int x,y,len;}wei[N];struct edge{int to,next;}e[N*2];int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}void addedge(int u,int v){ e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;}int find(int x){ if (f[x]==x) return x; f[x]=find(f[x]); return f[x];}void build(int x){ dep[x]=dep[fa[x][0]]+1; for (int i=1;i<=18;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for (int i=last[x];i;i=e[i].next) { if (e[i].to==fa[x][0]) continue; fa[e[i].to][0]=x; build(e[i].to); }}int get_len(int x,int y){ int x1=x,y1=y; if (dep[x]<dep[y]) swap(x,y); for (int i=18;i>=0;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i]; if (x==y) return dep[x1]+dep[y1]-2*dep[x]; for (int i=18;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return dep[x1]+dep[y1]-2*dep[fa[x][0]];}int main(){ freopen("hike.in","r",stdin);freopen("hike.out","w",stdout); int ty=read(); n=read();q=read(); int lastans=0; for (int i=1;i<=n;i++) wei[i].x=wei[i].y=f[i]=i,size[i]=1,dep[i]=1; while (q--) { int op=read(); if (op==1) { int x=read(),y=read(); if (ty) x^=lastans,y^=lastans; int fx=find(x),fy=find(y); if (size[fx]>size[fy]) swap(x,y),swap(fx,fy); f[fx]=fy;size[fy]+=size[fx]; addedge(x,y); fa[x][0]=y; build(x); int a[2],b[2]; a[0]=wei[fx].x;a[1]=wei[fx].y;b[0]=wei[fy].x;b[1]=wei[fy].y; if (wei[fx].len>wei[fy].len) wei[fy].x=a[0],wei[fy].y=a[1],wei[fy].len=wei[fx].len; for (int i=0;i<=1;i++) for (int j=0;j<=1;j++) { int w=get_len(a[i],b[j]); if (w>wei[fy].len) wei[fy].len=w,wei[fy].x=a[i],wei[fy].y=b[j]; } } else { int x=read(); if (ty) x^=lastans; int y=find(x); lastans=max(get_len(x,wei[y].x),get_len(x,wei[y].y)); printf("%d\n",lastans); } } return 0;}
0 0
- jzoj 5012. 【NOI2017模拟3.13】远行 启发式合并
- 【JZOJ 100019】【NOI2017模拟6.26】A
- JZOJ 100019【NOI2017模拟6.26】A
- JZOJ 5043. 【NOI2017模拟4.4】保持平衡
- jzoj 4996. 【NOI2017模拟3.1】游戏 扫描线+treap
- jzoj 5000. 【NOI2017模拟3.4】保镖 hall定理+搜索
- jzoj 5001. 【NOI2017模拟3.4】Trie树 状压dp
- jzoj 5006. 【NOI2017模拟3.8】A 树形dp
- jzoj 5015. 【NOI2017模拟3.15】决斗 贪心+平衡树
- jzoj 5020. 【NOI2017模拟3.17】牛奶装瓶 线段树
- jzoj 5023. 【NOI2017模拟3.18】Squence 莫队算法
- jzoj 5039. 【NOI2017模拟4.2】查询 线段树
- jzoj 5040. 【NOI2017模拟4.2】押韵 trie树+树形dp
- jzoj 5045. 【NOI2017模拟4.5】无限棋盘 hash+倍增
- [启发式合并] [模拟] [BZOJ5040] 未来研究
- jzoj 4999. 【NOI2017模拟3.3】螺旋序列 不删除版莫队算法
- jzoj 5016. 【NOI2017模拟3.15】数列 最长不下降序列+树状数组
- jzoj 5026. 【NOI2017模拟3.19】Number 状压dp+大整数分解
- SpringMvc常用注解总结
- C++第二次作业博客
- 12个使Pandas效率倍增的技巧—下
- GYM 101128 G.Game of Cards(博弈论)
- 判断一个点与圆的关系
- jzoj 5012. 【NOI2017模拟3.13】远行 启发式合并
- opencv入门学习(有关视频)
- 文章标题
- 转屏时,防止activity重建,保持activity内容
- sql学习 mysql
- svn diff svn log实例
- [BZOJ 3144][Hnoi2013]切糕(最小割)
- 深入理解Java之线程池
- 接口开发个人总结