[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][ ...
随机推荐
- 转:.net设计模式之工厂模式
原文:http://terrylee.cnblogs.com/archive/2006/01/04/310716.html 概述 在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对 ...
- Python基础第一篇-------python的介绍
一.python的介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆(中文名字:龟叔)为了在阿姆斯特丹打发时间,决心开发一个新的脚本 ...
- 将Model对象转换成json文本或者json二进制文件
将Model对象转换成json文本或者json二进制文件 https://github.com/casatwy/AnyJson 注意:经过测试,不能够直接处理字典或者数组 主要源码的注释 AJTran ...
- centos7.4 nfs-2.3.2
http://www.linuxfromscratch.org/blfs/view/svn/basicnet/libtirpc.html 注释:安装环境centos7.4; 安装完软件成后会升级系 ...
- ZT eoe android4.2 Bluetooth记录01-结构和代码分布
android4.2 Bluetooth记录01-结构和代码分布 作者:cnhua5更新于 08月21日访问(697)评论(2) 在android4.2中,Google更换了android的蓝牙协议栈 ...
- APP案例分析-摩拜单车app
第二次作业-App案例分析 本次案例分析选用的是 摩拜单车IOS5.7.5版本 测试环境为 IPhone 6s (IOS11.0.1,含有3DTOUCH功能).本次案例分析仅针对APP 而言,并不涉及 ...
- 将本地已有项目上传到github
1.在github上创建一个文件 2.看本地C盘中是否有.ssh文件夹 (C:\Users\用户名\.ssh) 检测有没有.ssh文件夹:执行命令 cd ~/.ssh 如果没有的话执行git命令: ...
- 使用Yarn+Webpack+Babel6搭建React.js环境
使用Yarn+Webpack+Babel6搭建React.js环境 Facebook开源的React.js已经改变了世人对前端UI的思考方式.这种基于组件方式的优势之一,就是使View更加的简单,因为 ...
- [JSOI2008]Blue Mary的战役地图
嘟嘟嘟 当看到n <= 50 的时候就乐呵了,暴力就行了,不过最暴力的方法是O(n7)……然后加一个二分边长达到O(n6logn),然后我们接着优化,把暴力比对改成O(1)的比对hash值,能达 ...
- Hadoop学习之路(八)在eclispe上搭建Hadoop开发环境
一.添加插件 将hadoop-eclipse-plugin-2.7.5.jar放入eclipse的plugins文件夹中 二.在Windows上安装Hadoop2.7.5 版本最好与Linux集群中的 ...