3123: [Sdoi2013]森林

Time Limit: 20 Sec   Memory Limit: 512 MB
Submit: 1905   Solved: 587
[ Submit][ Status][ Discuss]

Description

Input

第一行包含一个正整数testcase,表示当前测试数据的测试点编号。保证1≤testcase≤20。 
第二行包含三个整数N,M,T,分别表示节点数、初始边数、操作数。第三行包含N个非负整数表示 N个节点上的权值。 
 接下来 M行,每行包含两个整数x和 y,表示初始的时候,点x和点y 之间有一条无向边, 接下来 T行,每行描述一个操作,格式为“Q x y k”或者“L x y ”,其含义见题目描述部分。

Output

对于每一个第一类操作,输出一个非负整数表示答案。

Sample Input

1
8 4 8
1 1 2 2 3 3 4 4
4 7
1 8
2 4
2 1
Q 8 7 3 Q 3 5 1
Q 10 0 0
L 5 4
L 3 2 L 0 7
Q 9 2 5 Q 6 1 6

Sample Output

2
2
1
4
2

HINT

对于第一个操作 Q 8 7 3,此时 lastans=0,所以真实操作为Q 8^0 7^0 3^0,也即Q 8 7 3。点8到点7的路径上一共有5个点,其权值为4 1 1 2 4。这些权值中,第三小的为 2,输出 2,lastans变为2。对于第二个操作 Q 3 5 1 ,此时lastans=2,所以真实操作为Q 3^2 5^2 1^2 ,也即Q 1 7 3。点1到点7的路径上一共有4个点,其权值为 1 1 2 4 。这些权值中,第三小的为2,输出2,lastans变为 2。之后的操作类似。

可持久化线段树+启发式合并

如果只有查询操作,每次询问找到两个点的LCA,然后用可持久化线段树加加减减查询第k大即可。

对于连接操作我们要用启发式合并,把小的集合合并到大的上面,并把小的暴力重建主席树。

这样时间和空间复杂度就是O(n*logn^2)。

这道题我调了好久好久...后来要了数据才发现即使testcase>1也只有一组数据hhhh...数据坑爹怪我吗

然而把这个改了还是RE,原来是加边的cnt和主席树的cnt搞混了...啊啊啊欲哭无泪

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define N 100005
#define M 40000000
#define inf 1000000000
using namespace std;
int n,m,t,cnt,cnt_e,ans;
int a[N],head[N],rt[N],f[N],sum[N],dep[N],fa[N][20];
int sz[M],ls[M],rs[M];
struct edge_type{int next,to;}e[N*2];
inline 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;
}
inline void add_edge(int x,int y)
{e[++cnt_e]=(edge_type){head[x],y};head[x]=cnt_e;e[++cnt_e]=(edge_type){head[y],x};head[y]=cnt_e;
}
int find(int x)
{return f[x]==x?x:f[x]=find(f[x]);
}
void merge(int x,int y)
{int fx=find(x),fy=find(y);f[fx]=fy;sum[fy]+=sum[fx];
}
int lca(int x,int y)
{if (dep[x]<dep[y]) swap(x,y);D(i,19,0) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];if (x==y) return x;D(i,19,0) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];return fa[x][0];
}
void insert(int x,int &y,int l,int r,int val)
{if (!y) y=++cnt;sz[y]=sz[x]+1;if (l==r) return;int mid=(l+r)>>1;if (val<=mid) rs[y]=rs[x],insert(ls[x],ls[y],l,mid,val);else ls[y]=ls[x],insert(rs[x],rs[y],mid+1,r,val);
}
int getkth(int x,int y,int z,int w,int l,int r,int k)
{if (l==r) return l;int mid=(l+r)>>1;int tmp=sz[ls[x]]+sz[ls[y]]-sz[ls[z]]-sz[ls[w]];if (k<=tmp) return getkth(ls[x],ls[y],ls[z],ls[w],l,mid,k);else return getkth(rs[x],rs[y],rs[z],rs[w],mid+1,r,k-tmp);
}
void dfs(int x)
{F(i,1,19) fa[x][i]=fa[fa[x][i-1]][i-1];dep[x]=dep[fa[x][0]]+1;rt[x]=0;insert(rt[fa[x][0]],rt[x],0,inf,a[x]);for(int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0]){fa[e[i].to][0]=x;dfs(e[i].to);}
}
int main()
{int hhh=read();n=read();m=read();t=read();F(i,1,n) a[i]=read();F(i,1,n) f[i]=i,sum[i]=1;F(i,1,m){int x=read(),y=read();add_edge(x,y);merge(x,y);}F(i,1,n) if (!fa[i][0]) dfs(i);F(i,1,t){char opt=getchar();while (opt!='Q'&&opt!='L') opt=getchar();if (opt=='Q'){int x=read()^ans,y=read()^ans,k=read()^ans,lc=lca(x,y);ans=getkth(rt[x],rt[y],rt[lc],rt[fa[lc][0]],0,inf,k);printf("%d\n",ans);}else{int x=read()^ans,y=read()^ans,fx=find(x),fy=find(y);if (sum[fx]>sum[fy]) swap(x,y);add_edge(x,y);merge(x,y);fa[x][0]=y;dfs(x);}}return 0;
}

bzoj3123【SDOI2013】森林相关推荐

  1. BZOJ3123: [Sdoi2013]森林

    BZOJ3123: [Sdoi2013]森林 Description 小Z有一片森林,含有N个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有M条边. 小Z希望执行T个操作,操作有两类: ...

  2. [bzoj3123][SDOI2013]森林

    3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 1654 Solved: 520 [Submit][Status] ...

  3. BZOJ3123[Sdoi2013]森林——主席树+LCA+启发式合并

    题目描述 输入 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20.  第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非 ...

  4. P3302 SDOI2013森林

    P3302 [SDOI2013]森林 题意: 一片森林,有n个节点,m个边,现在有t个操作, Q x y k:Q x y k 查询点 x 到点 y 路径上所有的权值中,第 ·k 小的权值是多少 L x ...

  5. 【BZOJ-3123】森林 主席树 + 启发式合并

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 2738  Solved: 806 [Submit][Statu ...

  6. [SDOI2013]森林(树上主席树+启发式合并+lca)

    链接:https://ac.nowcoder.com/acm/problem/20577 来源:牛客网 题目描述 小Z有一片森林,含有N个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有 ...

  7. 洛谷 P3302 [SDOI2013]森林 主席树+启发式合并

    click here~:https://www.luogu.org/problem/P3302 emmm这个题是真的烦 一看题发现这题不是count on a tree的升级版么 如果一点思路没有的话 ...

  8. 大学生笔记本选Mac还是Windows?

    先说结论,选Mac ! Mac颜值高,便携,续航好,课余时间外出自习,即使不外接电源,Mac也能用一整天. 当代短视频非常火,如果你想做视频剪辑,有Final Cut Pro 和Adobe Pr 任君 ...

  9. 可持久化汇总(讲解+题目)

    可持久化(一) 可持久化(二) 可持久化3–可持久化01Trie 可持久化4–可持久化并查集 各模块的例题都在各自讲解下面有写 下面是加强练习 练习题讲解--肖然老师的博客 练习题: P4137 Rm ...

最新文章

  1. C/C++面试题分享
  2. Kotlin for Android
  3. 关于数据库group by需要注意
  4. python 线程安全链表_教你用 Python 实现 HashMap 数据结构
  5. symantec antivirus 10.0服务器通讯问题
  6. SAP云平台里Run index.html和Run as SAP Fiori Launchpad的区别
  7. LeetCode 934. 最短的桥(2次BFS)
  8. Linux系统下MySQL导出数据库和导入数据库的命令
  9. ARM全新Armv9架构:10年最大更新、增强AI和security能力
  10. python AES对称加密文件、解密文件
  11. Power BI中的AI语义分析应用:《辛普森一家》
  12. 苹果电脑拷贝文件到u盘很慢_小米最硬核U盘!20g,3.1接口,120MB/S读取速度,可连iphone华为...
  13. openSUSE安装WPS
  14. 【机器学习】拉普拉斯平滑
  15. 使用Git提交代码时出现Author identity unknow
  16. 网络基础知识:10M、50M、100M宽带下载速率一般是多少?
  17. 儿童食品安全Word电子手抄报
  18. Hadoop之金庸江湖人物关系网分析
  19. GmSSL制作国密算法自签证书和 HTTPS 配置
  20. 二、深入理解运行时数据区

热门文章

  1. 流量分类方法设计(一)——参考论文整理
  2. pip install时报错超时(pip._vendor.requests.packages.urllib3.exceptions.ReadTimeoutError: HTTPSConnec)解决方案
  3. style常见的样式属性
  4. 基于 OpenCV + Python 的人脸识别上课签到系统
  5. SQLServer 连接不上 找不到网络路径
  6. 外网远程访问群晖NAS,内网穿透
  7. 法拉克机器人自动怎么调_FANUC机器人程序自动启动介绍汇总.ppt
  8. 如何把一张pdf分成多个?一个pdf怎么分成若干个pdf?
  9. mathtype左对齐
  10. [UVM]UVM TLM1.0 Interface归纳总结 --- 图解UVM TLM1.0 Interface