BZOJ - 3123 森林 (可持久化线段树+启发式合并)
先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树。当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组。树的结点数可以用并查集来维护。总复杂度$O(nlog^2n)$。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+,inf=0x3f3f3f3f;
int a[N],b[N],n2,hd[N],ne,n,m,nq,fa[N][],dep[N],siz[N],fa2[N],rt[N],ls[N*],rs[N*],val[N*],tot,vis[N];
struct E {int v,nxt;} e[N<<];
void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
int fd(int x) {return ~fa2[x]?fa2[x]=fd(fa2[x]):x;}
int mgg(int x,int y) {
int fx=fd(x),fy=fd(y);
if(fx==fy)return ;
fa2[fx]=fy,siz[fy]+=siz[fx];
return ;
}
#define mid ((l+r)>>1)
int lca(int u,int v) {
if(dep[u]<dep[v])swap(u,v);
for(int i=; i>=&&dep[u]>dep[v]; --i)if(dep[fa[u][i]]>=dep[v])u=fa[u][i];
if(u==v)return u;
for(int i=; i>=; --i)if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
return fa[u][];
}
void upd(int& u,int v,int x,int l=,int r=n2) {
if(!u)u=++tot;
val[u]=val[v]+;
if(l==r)return;
if(x<=mid)upd(ls[u],ls[v],x,l,mid),rs[u]=rs[v];
else upd(rs[u],rs[v],x,mid+,r),ls[u]=ls[v];
}
int qry(int u,int v,int w1,int w2,int k,int l=,int r=n2) {
if(l==r)return l;
int cnt=val[ls[u]]+val[ls[v]]-val[ls[w1]]-val[ls[w2]];
return k<=cnt?qry(ls[u],ls[v],ls[w1],ls[w2],k,l,mid):qry(rs[u],rs[v],rs[w1],rs[w2],k-cnt,mid+,r);
}
void dfs(int u,int f,int d,int flag) {
if(flag&&vis[u])return;
vis[u]=;
fa[u][]=f,dep[u]=d,rt[u]=,upd(rt[u],rt[f],a[u]);
for(int i=; i<; ++i)fa[u][i]=fa[fa[u][i-]][i-];
for(int i=hd[u]; ~i; i=e[i].nxt) {
int v=e[i].v;
if(v==f)continue;
dfs(v,u,d+,flag);
}
}
void mg(int u,int v) {
if(siz[fd(u)]>siz[fd(v)])swap(u,v);
addedge(u,v),addedge(v,u),mgg(u,v),dfs(u,v,dep[v]+,);
}
int main() {
scanf("%*d");
memset(hd,-,sizeof hd),ne=;
memset(fa2,-,sizeof fa2);
scanf("%d%d%d",&n,&m,&nq);
for(int i=; i<=n; ++i)scanf("%d",&a[i]);
for(int i=; i<=n; ++i)b[i-]=a[i];
sort(b,b+n),n2=unique(b,b+n)-b;
for(int i=; i<=n; ++i)a[i]=lower_bound(b,b+n2,a[i])-b+;
for(int i=; i<=n; ++i)siz[i]=;
while(m--) {
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v),addedge(v,u),mgg(u,v);
}
for(int i=; i<=n; ++i)dfs(i,,,);
for(int last=; nq--;) {
char ch;
int u,v,k;
scanf(" %c",&ch);
if(ch=='Q') {
scanf("%d%d%d",&u,&v,&k),u^=last,v^=last,k^=last;
int w=lca(u,v),ans=b[qry(rt[u],rt[v],rt[w],rt[fa[w][]],k)-];
printf("%d\n",ans),last=ans;
} else {
scanf("%d%d",&u,&v),u^=last,v^=last;
mg(u,v);
}
}
return ;
}
BZOJ - 3123 森林 (可持久化线段树+启发式合并)的更多相关文章
- bzoj 3123 可持久化线段树启发式合并
首先没有连边的操作的时候,我们可以用可持久化线段树来维护这棵树的信息,建立权值可持久化线段树,那么每个点继承父节点的线段树,当询问为x,y的时候我们可以询问rot[x]+rot[y]-rot[lca( ...
- bzoj 3673&3674 可持久化并查集&加强版(可持久化线段树+启发式合并)
CCZ在2015年8月25日也就是初三暑假要结束的时候就已经能切这种题了%%% 学习了另一种启发式合并的方法,按秩合并,也就是按树的深度合并,实际上是和按树的大小一个道理,但是感觉(至少在这题上)更好 ...
- [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)
[BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...
- [BZOJ 2653] middle(可持久化线段树+二分答案)
[BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...
- Bzoj 2733: [HNOI2012]永无乡(线段树+启发式合并)
2733: [HNOI2012]永无乡 Time Limit: 10 Sec Memory Limit: 128 MB Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己 ...
- 【bzoj2653】middle 可持久化线段树区间合并
题目描述 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[ ...
- [CSP-S模拟测试]:模板(ac)(线段树启发式合并)
题目描述 辣鸡$ljh\ NOI$之后就退役了,然后就滚去学文化课了.他每天都被$katarina$大神虐,仗着自己学过一些姿势就给$katarina$大神出了一道题.有一棵$n$个节点的以$1$号节 ...
- [ZJOI2019]语言(树链剖分+动态开点线段树+启发式合并)
首先,对于从每个点出发的路径,答案一定是过这个点的路径所覆盖的点数.然后可以做树上差分,对每个点记录路径产生总贡献,然后做一个树剖维护,对每个点维护一个动态开点线段树.最后再从根节点开始做一遍dfs, ...
- 【Codechef FRBSUM】【FJOI2016】【BZOJ4299】【BZOJ 4408】 可持久化线段树
4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 475 Solved: 287[Submit][Status ...
随机推荐
- Python进阶(2)_进程与线程的概念
1 进程与线程相关概念 1.1 进程 进程定义: 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成,是最小的资源管理单元 程序:用来描述进程要完成哪些功能 ...
- ajax使用formdata 提交excel文件表单到rails解析
.modal-body .container-fluid .row .col-md-12 1.下载模板文件 = link_to '模板文件' .row .col-md-12 = form_tag '' ...
- python cookboo 文件与IO 函数
写出文本数据 g = open('test.txt', 'rt', newline='',encoding = 'utf-8', errors='replace') t是windows平台特有的所谓t ...
- hadoop06---多线程
.1.1. 实现线程的两种方式 1.继承Thread的方式 见代码MyThreadWithExtends 2.声明实现 Runnable 接口的方式 见代码MyThreadWithImpliment ...
- centos中安装php7
centos7下安装php7 php7 centos7 安装PHP7 首先安装一些必须的依赖,这里就不阐述了,后面文章再细说 yum install -y \ gcc-c++ autoconf \ l ...
- Shell编程之case条件
一.case条件语句 1.语法 case "变量" in 值 1) 指令 1... ;; 值 2) 指令 2... ;; *) 指令 3... esac case条件语句的执行流程 ...
- HBase-存储-写路径
写路径 当用户向HRegionServer发起put请求时,其会将请求交给对应的HRegion实例来处理.第一步是要决定数据是否需要写到由HLog类实现的预写日志中.WAL是标准的Hadoop Seq ...
- 初探MyBatis之HelloWorld(一)
官方地址:https://github.com/mybatis/mybatis-3 准备: 官方中文文档地址:http://www.mybatis.org/mybatis-3/zh/getting-s ...
- codeforces 705A:Hulk
Description Dr. Bruce Banner hates his enemies (like others don't). As we all know, he can barely ta ...
- Redis 创建多个端口
默认的是6379 可以用6380,6381开启多个 1.开启 ./redis-server ../etc/redis.6380.conf & 2.链接 redis-cli -p 6380 查看 ...