BZOJ3123:[SDOI2013]森林——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=3123
https://www.luogu.org/problemnew/show/P3302
树上主席树操作方法看:http://www.cnblogs.com/luyouqi233/p/8159528.html
这题要动态树,显然不可能LCT套主席树啊。
那我们完全可以启发式合并一下主席树。
剩下的操作就很简单了。
(然而我debug两个小时才发现我n定义了两个emmmm)
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=8e4+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct tree{
int l,r,sum;
}tr[N*];
struct node{
int to,nxt;
}edge[N*];
int a[N],b[N],rt[N],pool,n,m;
int dep[N],anc[N][],son[N];
int cnt,head[N],fa[N],vis[N],tot;
inline void add(int u,int v){
edge[++cnt].to=v;edge[cnt].nxt=head[u];head[u]=cnt;
}
inline void insert(int y,int &x,int l,int r,int p){
tr[x=++pool]=tr[y];tr[x].sum++;
if(l==r)return;
int mid=(l+r)>>;
if(p<=mid)insert(tr[y].l,tr[x].l,l,mid,p);
else insert(tr[y].r,tr[x].r,mid+,r,p);
}
inline int query(int nl,int nr,int nm,int nfm,int l,int r,int k){
if(l==r)return l;
int delta=tr[tr[nl].l].sum+tr[tr[nr].l].sum-tr[tr[nm].l].sum-tr[tr[nfm].l].sum;
int mid=(l+r)>>;
if(delta>=k)return query(tr[nl].l,tr[nr].l,tr[nm].l,tr[nfm].l,l,mid,k);
else return query(tr[nl].r,tr[nr].r,tr[nm].r,tr[nfm].r,mid+,r,k-delta);
}
inline void LSH(){
sort(b+,b+m+);
m=unique(b+,b+m+)-b-;
for(int i=;i<=n;i++){
a[i]=lower_bound(b+,b+m+,a[i])-b;
}
return;
}
inline int LCA(int i,int j){
if(dep[i]<dep[j])swap(i,j);
for(int k=;k>=;k--){
if(dep[anc[i][k]]>=dep[j])i=anc[i][k];
}
if(i==j)return i;
for(int k=;k>=;k--){
if(anc[i][k]!=anc[j][k])i=anc[i][k],j=anc[j][k];
}
return anc[i][];
}
int find(int x){
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
void dfs(int u,int f,int root){
anc[u][]=f;
for(int k=;k<=;k++)
anc[u][k]=anc[anc[u][k-]][k-];
son[root]++;dep[u]=dep[f]+;fa[u]=root;vis[u]=;
insert(rt[f],rt[u],,m,a[u]);
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v!=f)dfs(v,u,root);
}
return;
}
int main(){
read();
n=read();int e=read(),T=read(),last=;
for(int i=;i<=n;i++)
a[i]=b[++m]=read(),fa[i]=i;
LSH();
for(int i=;i<=e;i++){
int x=read(),y=read();
add(x,y);add(y,x);
}
for(int i=;i<=n;i++)
if(!vis[i]){
dfs(i,,++tot);fa[tot]=tot;
}
for(int i=;i<=T;i++){
char ch=getchar();
while(ch!='Q'&&ch!='L')ch=getchar();
if(ch=='Q'){
int x=read()^last,y=read()^last,k=read()^last;
int t=LCA(x,y),ft=anc[t][];
printf("%d\n",last=b[query(rt[x],rt[y],rt[t],rt[ft],,m,k)]);
}else{
int x=read()^last,y=read()^last;
add(x,y);add(y,x);
int u=find(x),v=find(y);
if(son[u]<son[v]){
swap(u,v);
swap(x,y);
}
dfs(y,x,u);
}
}
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ3123:[SDOI2013]森林——题解的更多相关文章
- [BZOJ3123][Sdoi2013]森林 主席树+启发式合并
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当 ...
- [bzoj3123][Sdoi2013]森林_主席树_启发式合并
森林 bzoj-3123 Sdoi-2013 题目大意:给定一片共n个点的森林,T个操作,支持:连接两个不在一棵树上的两个点:查询一棵树上路径k小值. 注释:$1\le n,T \le 8\cdot ...
- BZOJ3123: [Sdoi2013]森林(启发式合并&主席树)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4813 Solved: 1420[Submit][Status ...
- [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)
Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...
- 【主席树 启发式合并】bzoj3123: [Sdoi2013]森林
小细节磕磕碰碰浪费了半个多小时的时间 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M ...
- bzoj3123 [Sdoi2013]森林 树上主席树+启发式合并
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3123 题解 如果是静态的查询操作,那么就是直接树上主席树的板子. 但是我们现在有了一个连接两棵 ...
- bzoj3123: [Sdoi2013]森林
题面传送门 复出的第一道题.. md就遇到坑了.. 简单来说就是可持久化线段树+启发式合并啊.. 感觉启发式合并好神奇好想学 每一次建边就暴力合并,每一个节点维护从根到它的权值线段树 按照题面的话最省 ...
- BZOJ3123[Sdoi2013]森林——主席树+LCA+启发式合并
题目描述 输入 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负 ...
- bzoj千题计划258:bzoj3123: [Sdoi2013]森林
http://www.lydsy.com/JudgeOnline/problem.php?id=3123 启发式合并主席树 #include<cmath> #include<cstd ...
随机推荐
- 怎样下载JDBC驱动
MySQL官网: https://www.mysql.com/ 请注意: 需要把mysql-connector-java-5.1.45-bin.jar放到C:\JMeter\apache-jmeter ...
- Linux命令应用大词典-第37章 Linux系统故障排错
37.1 mkbootdisk:创建用于运行系统的独立启动软盘 37.2 chroot:切换根目录环境 37.3 badblocks:搜索设备的坏块 37.4 mkinitrd:创建要载入ramdis ...
- (Python爬虫02) 制定爬虫的学习计划了
公司清退是件很让人郁闷的事情,精,气,神 都会受到影响.焦虑的心态,涣散的眼神, 无所适从的若无其事,人周茶凉的快速交接,各种担忧....平静的面孔波涛汹涌的心.... 认识聊天中满满的套路...还有 ...
- leetcode-峰值检测
寻找峰值 峰值元素是指其值大于左右相邻值的元素. 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引. 数组可能包含多个峰值,在这种情况下,返回 ...
- Java学习笔记-10.io流
1.输入流,只能从中读取数据,而不能向其写出数据.输出流,只能想起写入字节数据,而不能从中读取. 2.InputStream的类型有: ByteArrayInputStream 包含一个内存缓冲区,字 ...
- Linux内核设计笔记12——内存管理
内存管理学习笔记 页 页是内核管理内存的基本单位,内存管理单元(MMU,管理内存并把虚拟地址转化为物理地址的硬件)通常以页为单位进行处理,从虚拟内存的角度看,页就是最小单位. struct page{ ...
- 十面阿里,七面头条,六个Offer,春招结束
作者:jkgeekjack链接:https://www.nowcoder.com/discuss/80156?type=0&order=0&pos=13&page=2来源:牛客 ...
- Python中的赋值语法
Python中复制语法有6种 Basic Form >>>spam = 'spam' Tuple assignment >>>spam, ham = 'spam', ...
- iOS- 非ARC的项目内存管理细节详解(实战)
1.前言 接上文:iOS- 如何将非ARC的项目转换成ARC项目(实战) 2.内存管理时相关的配置 当我们把将非ARC的内存管理都管理好后,发现在做有些操作的时候内存还是在一直的缓慢增加 比如做一个最 ...
- 《学习OpenCV》课后习题解答6
题目:(P104) 使用cvCmp()创建一个掩码.加载一个真实的图像.使用cvsplit()将图像分割成红,绿,蓝三个单通道图像. a.找到并显示绿图. b.克隆这个绿图两次(分别命名为clone1 ...