[IOI2018] werewolf 狼人 kruskal重构树,主席树
[IOI2018] werewolf 狼人
kruskal重构树好题。
日常安利博客文章
这题需要搞两棵重构树出来,这两棵重构树和我们平时见过的重构树有点不同(据说叫做点权重构树?),根据经过我们简化的建树方法,这两棵树不再是二叉树,但是仍具有kruskal重构树的优秀性质,建议结合后面的描述理解。
看这题需要首先我们从\(S\)走到\(T\)转化为分别从\(S\)和\(T\)出发寻找能共同到达的点,需要快速求出从某个点出发经过点权不大(小)于\(r\)(\(l\))的点,考虑kruskal重构树。令每条边的的边权为所连接两点的较大(小)值,造两棵重构树,这样就可以像平时一样直接倍增做了,但是我们发现边权的信息实际上就是点权的信息,于是我们在建新树时就不另建新点了,这就是所谓的“点权重构树”。建出树处理倍增之后,我们的问题就变成了查询两棵树上两棵子树是否有交,用dfs序表达就是一个简单的二维数点的问题,直接主席树。
#include <cstdio>
#include <cctype>
#include <vector>
#define R register
#define I inline
#define B 1000000
using namespace std;
const int N = 200003;
char buf[B], *p1, *p2;
I char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, B, stdin), p1==p2) ? EOF : *p1++; }
I int rd() {
R int f = 0;
R char c = gc();
while (c < 48 || c > 57) c = gc();
while (c > 47 && c < 58) f = f * 10 + (c ^ 48), c = gc();
return f;
}
int s[N], rt[N], val[N], T;
vector <int> g[N];
struct edge { int g, s; };
struct segtree { int p, q, s; }e[N << 5];
struct kruskal {
int h[N], f[N], fa[N][20], dfn[N], low[N], E, tim;
edge e[N];
I void add(int x, int y) { e[++E] = (edge){y, h[x]}, h[x] = E; }
I int find(int x) {
R int r = x, y;
while (f[r] ^ r)
r = f[r];
while (x ^ r)
y = f[x], f[x] = r, x = y;
return r;
}
void dfs(int x) {
dfn[x] = ++tim;
R int i;
for (i = 1; i < 20; ++i)
fa[x][i] = fa[fa[x][i - 1]][i - 1];
for (i = h[x]; i; i = e[i].s)
dfs(e[i].g);
low[x] = tim;
}
}X, Y;
int modify(int k, int l, int r, int x) {
R int t = ++T;
e[t].p = e[k].p, e[t].q = e[k].q, e[t].s = e[k].s + 1;
if (l == r)
return t;
R int m = l + r >> 1;
if (x <= m)
e[t].p = modify(e[k].p, l, m, x);
else
e[t].q = modify(e[k].q, m + 1, r, x);
return t;
}
int query(int k, int t, int l, int r, int x, int y) {
if (x <= l && r <= y)
return e[t].s - e[k].s;
R int m = l + r >> 1, o = 0;
if (x <= m)
o += query(e[k].p, e[t].p, l, m, x, y);
if (m < y)
o += query(e[k].q, e[t].q, m + 1, r, x, y);
return o;
}
int main() {
R int n = rd(), m = rd(), Q = rd(), i, x, y, l, r;
for (i = 1; i <= m; ++i)
x = rd() + 1, y = rd() + 1, g[x].push_back(y), g[y].push_back(x);
for (i = 1; i <= n; ++i)
X.f[i] = i, Y.f[i] = i, s[i] = g[i].size();
for (x = n; x; --x)
for (i = 0; i < s[x]; ++i)
if (g[x][i] > x && (y = X.find(g[x][i])) ^ x)
X.add(x, y), X.f[y] = X.fa[y][0] = x;
for (x = 1; x <= n; ++x)
for (i = 0; i < s[x]; ++i)
if (g[x][i] < x && (y = Y.find(g[x][i])) ^ x)
Y.add(x, y), Y.f[y] = Y.fa[y][0] = x;
X.dfs(1), Y.dfs(n);
for (i = 1; i <= n; ++i)
val[X.dfn[i]] = Y.dfn[i];
for (i = 1; i <= n; ++i)
rt[i] = modify(rt[i - 1], 1, n, val[i]);
while (Q--) {
x = rd() + 1, y = rd() + 1, l = rd() + 1, r = rd() + 1;
for (i = 19; ~i; --i)
if (X.fa[x][i] >= l)
x = X.fa[x][i];
for (i = 19; ~i; --i)
if (Y.fa[y][i] && Y.fa[y][i] <= r)
y = Y.fa[y][i];
printf(query(rt[X.dfn[x] - 1], rt[X.low[x]], 1, n, Y.dfn[y], Y.low[y]) ? "1\n" : "0\n");
}
return 0;
}
[IOI2018] werewolf 狼人 kruskal重构树,主席树的更多相关文章
- [IOI2018] werewolf 狼人 [kruskal重构树+主席树]
题意: 当你是人形的时候你只能走 \([L,N-1]\) 的编号的点(即大于等于L的点) 当你是狼形的时候你只能走 \([1,R]\) 的编号的点(即小于等于R的点) 然后问题转化成人形和狼形能到的点 ...
- LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)
LOJ 洛谷 这题不就是Peaks(加强版)或者归程么..这算是\(IOI2018\)撞上\(NOI2018\)的题了? \(Kruskal\)重构树(具体是所有点按从小到大/从大到小的顺序,依次加入 ...
- luoguP4197:Peaks(Kruskal重构树+主席树)或者(点分树+离线)
题意:有N座山,M条道路.山有山高,路有困难值(即点权和边权).现在Q次询问,每次给出(v,p),让求从v出发,只能结果边权<=p的边,问能够到达的山中,第K高的高度(从大到小排序). 思路:显 ...
- UOJ#407. 【IOI2018】狼人 Kruskal,kruskal重构树,主席树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ407.html 题解 套路啊. 先按照两个节点顺序各搞一个kruskal重构树,然后问题转化成两棵krus ...
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
- BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增
题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...
- luogu4197 Peaks (kruskal重构树+主席树)
按照边权排序建出kruskal重构树,每次就变成了先找一个权值<=x的最远的祖先,然后看这个子树的第k小.离散化一下,在dfs序上做主席树即可 而且只需要建叶节点的主席树 注意输出的是第k小点的 ...
- 洛谷P4197 Peaks(Kruskal重构树 主席树)
题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...
- [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2438 Solved: 763[Submit][ ...
随机推荐
- SQL SERVER中的And与Or的优先级
数据库中有城市库表,其中有国家.省.城市. 举例:在广东省内(包含广东省本身),找出名称为“广州”的记录 首先,广东省内的条件是:ParentId = 2 Or Id =2 名称为“广州”的条件是:N ...
- 关于打开现有项目时数据库连接配置遇到的问题 连接字符串中的数据源值指定未安装的SQL Server的实例。要解决此问题,可选择安装匹配的SQL Server实例或修改连接字符串中的数据源值
最近在看红皮书<ASP.NET MVC 5 高级编程>时,为了更好理解,边看书,边打开源代码查看,在VS(Visual Studio 2015)中将源代码打开,发现数据库连接是关闭的,本想 ...
- Jquery 保留N位小数,且千位以上用","号隔开
s:数据Value n:保留小数位数 function jinEFmoney(s, n) { if (s == '' || s == null) return '0.00'; n = n > 0 ...
- 多数据源报错 expected single matching bean but found 2: xxx,xxx
问题: expected single matching bean but found 2: xxx,xxx 原因:在 Spring 容器中配置了两个类型Bean,Spring 容器将无法确定到底要用 ...
- Web通信协议:OSI、TCP、UDP、Socket、HTTP、HTTPS、TLS、SSL、WebSocket、Stomp
1 各层的位置 1.1 OSI七层模型全景图 OSI是Open System Interconnect的缩写,意为开放式系统互联. 1.2 五层网络协议 在七层的基础上, ...
- ZT C语言实现字符串倒序
http://blog.chinaunix.net/uid-20788517-id-34777.html 分类: C/C++ 1 #include <stdio.h> 2 #includ ...
- upper_bound()与lower_bound()的使用
upper_bound()与lower_bound()的使用 c++中的许多库函数可以使我们的代码量大大减少,也可使问题简单化.很早之前就接触了upper_bound()与lower_bound(), ...
- 【python库安装问题解决】UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc0 in position 121: invalid start byte
好久没用python了...今天随便pip安装个库突然报错: Exception:‘’ (most recent call last): File "C:\ProgramData\Anac ...
- tomcat 开启远程debug
修改 tomcat 目录下 /bin/catelina.sh # execution immediately after startup. Default is ...
- BZOJ3514:GERALD07加强版(LCT,主席树)
Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密. 接下来 ...