Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G题, 并查集 + 线段树合并)
题目链接 2016 ACM-ICPC EC-Final Problem G
题意 给定一个无向图。每个点有一种颜色。
现在给定$q$个询问,每次询问$x$和$w$,求所有能通过边权值不超过$w$的边走到$x$的点的集合中,哪一种颜色的点出现的次数最多。
次数相同时输出编号最小的那个颜色。强制在线。
求哪种颜色可以用线段树合并搞定。
关键是这个强制在线。
当每次询问的时候,我们先要求出最小生成树在哪个时刻恰好把边权值不超过$w$的边都用并查集合并了。
在做最小生成树的时候每合并两个节点,另外开一个新的结点,原来两个点的父亲都指向这个新的结点。
然后倍增预处理,用类似求$LCA$的方法来得到询问的那个时刻。
时间复杂度$O(nlogn)$
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 2e5 + 10;
const int M = N * 20; struct node{
int x, y, z;
void scan(){
scanf("%d%d%d", &x, &y, &z);
}
friend bool operator < (const node &a, const node &b){
return a.z < b.z;
}
} e[N]; int T, ca = 0;
int tot;
int n, m, q, ans;
int c[N], root[N], v[N], father[N];
int ls[M], rs[M], mx[M], ret[M];
int id, res[N];
int f[N][19]; int getfather(int x){
return father[x] == x ? x : father[x] = getfather(father[x]);
} void up(int i){
mx[i] = max(mx[ls[i]], mx[rs[i]]);
if (mx[i] == mx[ls[i]]) ret[i] = ret[ls[i]];
else ret[i] = ret[rs[i]];
} int build(int l, int r, int val){
int x = ++tot;
ls[x] = rs[x] = mx[x] = ret[x] = 0;
if (l == r){
mx[x] = 1;
ret[x] = val;
return x;
} int mid = (l + r) >> 1;
if (val <= mid) ls[x] = build(l, mid, val);
else rs[x] = build(mid + 1, r, val);
up(x);
return x;
} int Merge(int x, int y, int l, int r){
if (x == 0 || y == 0) return x + y;
if (l == r){
mx[x] += mx[y];
return x;
} int mid = (l + r) >> 1;
ls[x] = Merge(ls[x], ls[y], l, mid);
rs[x] = Merge(rs[x], rs[y], mid + 1, r);
up(x);
return x;
} int main(){ scanf("%d", &T);
while (T--){
tot = 0;
scanf("%d%d", &n, &m);
rep(i, 1, n) scanf("%d", c + i); rep(i, 1, n){
father[i] = i;
v[i] = 0;
f[i][0] = i;
root[i] = build(1, n, c[i]);
res[i] = ret[root[i]];
} id = n;
rep(i, 1, m) e[i].scan(); sort(e + 1, e + m + 1); rep(i, 1, m){
int x = e[i].x, y = e[i].y, z = e[i].z;
int fx = getfather(x), fy = getfather(y);
if (fx ^ fy){
++id;
f[id][0] = id;
father[id] = id;
v[id] = z;
father[fx] = father[fy] = id;
f[fx][0] = f[fy][0] = id;
root[id] = Merge(root[fx], root[fy], 1, n);
res[id] = ret[root[id]];
}
} rep(j, 1, 17){
rep(i, 1, id) f[i][j] = f[f[i][j - 1]][j - 1];
} printf("Case #%d:\n", ++ca);
scanf("%d", &q);
ans = 0;
while (q--){
int x, w;
scanf("%d%d", &x, &w);
x ^= ans, w ^= ans;
dec(i, 17, 0) if (v[f[x][i]] <= w) x = f[x][i];
printf("%d\n", ans = res[x]);
}
} return 0;
}
Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G题, 并查集 + 线段树合并)的更多相关文章
- ACM ICPC China final G Pandaria
目录 ACM ICPC China final G Pandaria ACM ICPC China final G Pandaria 题意:给一张\(n\)个点\(m\)条边的无向图,\(c[i]\) ...
- Codeforces 571D - Campus(并查集+线段树+DFS 序,hot tea)
Codeforces 题目传送门 & 洛谷题目传送门 看到集合的合并,可以本能地想到并查集. 不过这题的操作与传统意义上的并查集不太一样,传统意义上的并查集一般是用来判断连通性的,而此题还需支 ...
- Vladik and Entertaining Flags CodeForces - 811E (并查集,线段树)
用线段树维护每一块左右两侧的并查集, 同色合并时若不连通则连通块数-1, 否则不变 #include <iostream> #include <algorithm> #incl ...
- 2016 ACM/ICPC Asia Regional Shenyang Online 1003/HDU 5894 数学/组合数/逆元
hannnnah_j’s Biological Test Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K ...
- 2016 ACM/ICPC Asia Regional Qingdao Online 1001/HDU5878 打表二分
I Count Two Three Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- 2016 ACM/ICPC Asia Regional Shenyang Online 1009/HDU 5900 区间dp
QSC and Master Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) ...
- 2016 ACM/ICPC Asia Regional Shenyang Online 1007/HDU 5898 数位dp
odd-even number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- 2016 ACM/ICPC Asia Regional Dalian Online 1002/HDU 5869
Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K ( ...
- 2016 ACM/ICPC Asia Regional Dalian Online 1006 /HDU 5873
Football Games Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
随机推荐
- JMeter学习笔记(九) 参数化1--函数助手:_CSVRead
1.函数助手:_CSVRead 1)准备数据文件 ,文件可以是.csv格式,.dat格式,txt格式等 2)打开函数助手,生成参数 3)添加HTTP请求,引用参数 4)执行HTTP请求,察看结果树中的 ...
- Python全栈工程师(字符串/序列)
ParisGabriel Python 入门基础 字符串:str用来记录文本信息字符串的表示方式:在非注释中凡是用引号括起来的部分都是字符串‘’ 单引号“” 双引号''' ''' ...
- 【志银】NYOJ《题目524》A-B Problem
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=860 My思路: 先用两个字符串储存这两个实数,然后再用另外两个字符串储存去掉符号和前后多 ...
- Struts2 学习笔记
1)Strust2是以WebWork为核心,采用拦截器的机制对用户请求进行处理. 2)Struts2框架结构: 3)简单来看整个Struts2的处理过程可以简单的理解为 用户的请求发送给对应的Acti ...
- class内部处理
class A { public: int foo( ) { return val ; } static int staFun( ) { return staVal ; } static int st ...
- SystemTap 用法
SystemTap需要内核符号表: http://ddebs.ubuntu.com/pool/main/l/linux/ 基本语法: next对应C中的return,中途返回: 今晚遗留了两个问题: ...
- [poj] 3068 "Shortest" pair of paths || 最小费用最大流
[原题](http://poj.org/problem?id=3068) 给一个有向带权图,求两条从0-N-1的路径,使它们没有公共点且边权和最小 . //是不是像传纸条啊- 是否可行只要判断最后最大 ...
- The UVALIVE 7716 二维区间第k小
The UVALIVE 7716 二维区间第k小 /** 题意:给一个n * n的矩阵,有q个查询 每次查询r,c,s,k表示已(r,c)为右上角 大小为s的正方形中 第k小的元素 n <= 2 ...
- BZOJ4824 [Cqoi2017]老C的键盘 【树形dp】
题目链接 BZOJ4824 题解 观察出题目中的关系实际上是完全二叉树的父子关系 我们设\(f[i][j]\)为以\(i\)为根的节点在其子树中排名为\(j\)的方案数 转移时,枚举左右子树分别有几个 ...
- 【CZY选讲·Hja的棋盘】
题目描述 Hja特别有钱,他买了一个×的棋盘,然后Yjq到这个棋盘来搞事.一开始所有格子都是白的,Yjq进行次行操作次列操作,所谓一次操作,是将对应的行列上的所有格子颜色取反.现在Yjq希望搞事之后 ...