luogu3302 [SDOI2013]森林
前置技能:Count on a tree
然后带上一个启发式合并
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
int n, m, orz, uu, vv, ww, a[80005], b[80005], rnk[80005], rem, cnt, tt[15];
int hea[80005], fa[80005], siz[80005], gra[80005][19], qaq, lst;
int rot[80005], lson[9000005], rson[9000005], sum[9000005], dep[80005];
bool vis[80005];
char ss[15];
struct Edge{
int too, nxt;
}edge[320005];
void add_edge(int fro, int too){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
hea[fro] = cnt;
}
int insert(int pre, int l, int r, int x){
int rt=++qaq;
int mid=(l+r)>>1;
lson[rt] = lson[pre]; rson[rt] = rson[pre]; sum[rt] = sum[pre] + 1;
if(l==r) return rt;
if(x<=mid) lson[rt] = insert(lson[pre], l, mid, x);
if(mid<x) rson[rt] = insert(rson[pre], mid+1, r, x);
return rt;
}
void dfs(int o, int f, int r){
fa[o] = f;
siz[r]++;
dep[o] = dep[f] + 1;
vis[o] = true;
gra[o][0] = f;
for(int i=1; i<=16; i++)
gra[o][i] = gra[gra[o][i-1]][i-1];
rot[o] = insert(rot[f], 1, rem, rnk[o]);
for(int i=hea[o]; i; i=edge[i].nxt){
int t=edge[i].too;
if(t!=f) dfs(t, o, r);
}
}
int build(int l, int r){
int rt=++qaq;
int mid=(l+r)>>1;
if(l==r) return rt;
if(l<=mid) lson[rt] = build(l, mid);
if(mid<r) rson[rt] = build(mid+1, r);
return rt;
}
int getLca(int uu, int vv){
if(dep[uu]<dep[vv]) swap(uu, vv);
for(int i=16; i>=0; i--)
if(dep[gra[uu][i]]>=dep[vv])
uu = gra[uu][i];
if(uu==vv) return uu;
for(int i=16; i>=0; i--)
if(gra[uu][i]!=gra[vv][i]){
uu = gra[uu][i];
vv = gra[vv][i];
}
return gra[uu][0];
}
int query(int l, int r, int k){
int tmp=0;
tmp -= sum[lson[tt[1]]] + sum[lson[tt[2]]];
tmp += sum[lson[tt[3]]] + sum[lson[tt[4]]];
if(l==r) return l;
int mid=(l+r)>>1;
if(k<=tmp){
for(int i=1; i<=4; i++)
tt[i] = lson[tt[i]];
return query(l, mid, k);
}
else{
for(int i=1; i<=4; i++)
tt[i] = rson[tt[i]];
return query(mid+1, r, k-tmp);
}
}
int myfind(int x){
return x==fa[x]?x:fa[x]=myfind(fa[x]);
}
int main(){
cin>>n;
cin>>n>>m>>orz;
for(int i=1; i<=n; i++){
scanf("%d", &a[i]);
b[i] = a[i];
fa[i] = i;
}
sort(b+1, b+1+n);
rem = unique(b+1, b+1+n) - (b + 1);
for(int i=1; i<=n; i++){
int tmp=lower_bound(b+1, b+1+rem, a[i])-b;
rnk[i] = tmp;
}
for(int i=1; i<=m; i++){
scanf("%d %d", &uu, &vv);
add_edge(uu, vv);
add_edge(vv, uu);
}
rot[0] = build(1, rem);
for(int i=1; i<=n; i++)
if(!vis[i])
dfs(i, 0, i), fa[i]=i;
while(orz--){
scanf("%s", ss);
if(ss[0]=='Q'){
scanf("%d %d %d", &uu, &vv, &ww);
uu ^= lst; vv ^= lst; ww ^= lst;
int lca=getLca(uu, vv);
tt[1] = rot[lca]; tt[2] = rot[gra[lca][0]];
tt[3] = rot[uu]; tt[4] = rot[vv];
lst = b[query(1, rem, ww)];
printf("%d\n", lst);
}
else{
scanf("%d %d", &uu, &vv);
uu ^= lst; vv ^= lst;
int r1=myfind(uu);
int r2=myfind(vv);
if(siz[r1]<siz[r2]) swap(uu, vv), swap(r1, r2);
add_edge(uu, vv);
add_edge(vv, uu);
dfs(vv, uu, r1);
}
}
return 0;
}
luogu3302 [SDOI2013]森林的更多相关文章
- BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]
3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...
- luoguP3302 [SDOI2013]森林 主席树 启发式合并
题目链接 luoguP3302 [SDOI2013]森林 题解 本来这题树上主席树暴力启发式合并就完了 结果把lca写错了... 以后再也不这么写了 复杂度\(O(nlog^2n)\) "f ...
- P3302 [SDOI2013]森林(主席树+启发式合并)
P3302 [SDOI2013]森林 主席树+启发式合并 (我以前的主席树板子是错的.......坑了我老久TAT) 第k小问题显然是主席树. 我们对每个点维护一棵包含其子树所有节点的主席树 询问(x ...
- [BZOJ3123][Sdoi2013]森林 主席树+启发式合并
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当 ...
- BZOJ3123: [Sdoi2013]森林(启发式合并&主席树)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4813 Solved: 1420[Submit][Status ...
- 【BZOJ3123】[Sdoi2013]森林 主席树+倍增LCA+启发式合并
[BZOJ3123][Sdoi2013]森林 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整 ...
- 洛谷 P3302 [SDOI2013]森林 解题报告
P3302 [SDOI2013]森林 题目描述 小\(Z\)有一片森林,含有\(N\)个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有\(M\)条边. 小Z希望执行\(T\)个操作,操 ...
- 3123: [Sdoi2013]森林
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3336 Solved: 978[Submit][Status] ...
- bzoj 3123: [Sdoi2013]森林(45分暴力)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4184 Solved: 1235[Submit][Status ...
随机推荐
- codeforces 149D Coloring Brackets (区间DP + dfs)
题目链接: codeforces 149D Coloring Brackets 题目描述: 给一个合法的括号串,然后问这串括号有多少种涂色方案,当然啦!涂色是有限制的. 1,每个括号只有三种选择:涂红 ...
- Android课程设计第四天ListView运用
注意:课程设计只为完成任务,不做细节描述~ 效果图 <?xml version="1.0" encoding="utf-8"?> <Relat ...
- Database UVA - 1592
对于每组数据,首先通过一个map将每个字符串由一个数字代替,相同的字符串由相同数字代替,不同的字符串由不同数字代替.那么题目就变为了询问是否存在行r1,r2以及列c1,c2使得str[r1][c1]= ...
- AWVS11使用教程——Acunetix Web Vulnerability Scanner 11.x
AWVS11使用教程 一:普通扫描. 二:报告生成. 三:登陆扫描. Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的网络漏洞扫描工具,它通过网络爬虫测 ...
- UIBarButtonItem系统默认风格形状
typedef NS_ENUM(NSInteger, UIBarButtonSystemItem) { UIBarButtonSystemItemDone, UIBarButtonSystemItem ...
- AJPFX:不用递归巧妙求出1000的阶乘所有零和尾部零的个数
package com.jonkey.test; import java.math.BigInteger; public class Test6 { /*** @param args* 需求:求出1 ...
- 8.bootstrap下拉菜单、按钮组、按钮式下拉菜单
下拉菜单 dropdown 对齐方式: .dropdown-menu-right .dropdown-menu-left <div class="container" ...
- 字符串循环右移-c语言
一个长度为len的字符串,对其循环右移n位 [期望]char str[] = "abcdefg";右移3次后,变成"efgabcd" [思路] 思路1. 如果用 ...
- SPOJ COT2 Count on a tree II (树上莫队,倍增算法求LCA)
题意:给一个树图,每个点的点权(比如颜色编号),m个询问,每个询问是一个区间[a,b],图中两点之间唯一路径上有多少个不同点权(即多少种颜色).n<40000,m<100000. 思路:无 ...
- Linux之 if命令——简单的shell文件
如何写一个shell文件,写一个小脚本 1.新建一个脚本文件:vi demo.sh 2.追加执行权限: chmod u+x demo.sh 3.执行脚本:./demo.sh 4.什么是脚本?把一堆命令 ...