[IOI2018] werewolf 狼人 [kruskal重构树+主席树]
题意:
当你是人形的时候你只能走 \([L,N-1]\) 的编号的点(即大于等于L的点)
当你是狼形的时候你只能走 \([1,R]\) 的编号的点(即小于等于R的点)
然后问题转化成人形和狼形能到的点有没有交集。
solution:
发现可以建 kruskal重构树,就可以通过在树上倍增来求出来一个子树,这个子树内是你可以到的点。然后问题转化成了两个子树区间的交,这个问题可以用主席树解决。
定义 \(rev1_i\) 是在树上的第 \(i\) 个位置对应的数,那你定义 \(r_{rev1_i}=i\),那么 \(r_i\) 就是这个元素在树上出现的位置,\(rev2_i\)同理,即这个数在第二棵树上对应的数,然后主席树求解。
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0;
char c = getchar();
while (c < 48) c = getchar();
while (c > 47) x = x * 10 + (c - 48), c = getchar();
return x;
}
int n, m, q;
const int maxn = 4e5 + 54;
struct edge {
int u, v;
};
vector<edge> e;
int fa[maxn];
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
vector<int> g[maxn];
struct Tree {
int L[maxn], R[maxn], idx;
int rev[maxn], val[maxn], f[maxn][22];
void dfs(int u) {
if (u <= n) {
rev[L[u] = ++idx] = u;
val[u] = u;
} else
L[u] = idx + 1;
for (int i = 1; i <= 20; i++) f[u][i] = f[f[u][i - 1]][i - 1];
for (int v : g[u]) f[v][0] = u, dfs(v);
R[u] = idx;
}
int getu(int s, int l) {
for (int i = 20; ~i; i--)
if (f[s][i] && val[f[s][i]] >= l) s = f[s][i];
return s;
}
int getv(int t, int r) {
for (int i = 20; ~i; i--)
if (f[t][i] && val[f[t][i]] <= r) t = f[t][i];
return t;
}
} t1, t2;
int tot;
int rt[maxn], ls[maxn << 5], rs[maxn << 5], val[maxn << 5], cnt = 0;
void upd(int& p, int pre, int l, int r, int x) {
ls[p = ++cnt] = ls[pre], rs[p] = rs[pre], val[p] = val[pre] + 1;
if (l == r) return;
int mid = l + r >> 1;
if (x <= mid)
upd(ls[p], ls[pre], l, mid, x);
else
upd(rs[p], rs[pre], mid + 1, r, x);
}
int qry(int a, int b, int ql, int qr, int l, int r) {
if (ql <= l && r <= qr) return val[b] - val[a];
int mid = l + r >> 1, ans = 0;
if (ql <= mid) ans = qry(ls[a], ls[b], ql, qr, l, mid);
if (qr > mid) ans += qry(rs[a], rs[b], ql, qr, mid + 1, r);
return ans;
}
int main() {
n = read(), m = read(), q = read();
for (int i = 0; i < m; i++) {
int u = read(), v = read();
++u, ++v;
if (u > v) u ^= v ^= u ^= v;
e.push_back({ u, v });
}
for (int i = 1; i <= n * 2; i++) fa[i] = i, g[i].clear();
sort(e.begin(), e.end(), [](edge a, edge b) { return a.u > b.u; });
tot = n;
for (auto x : e) {
int u = find(x.u), v = find(x.v);
if (u == v) continue;
fa[u] = fa[v] = ++tot;
t1.val[tot] = x.u;
g[tot].push_back(u), g[tot].push_back(v);
}
t1.dfs(tot);
for (int i = 1; i <= n * 2; i++) fa[i] = i, g[i].clear();
sort(e.begin(), e.end(), [](edge a, edge b) { return a.v < b.v; });
tot = n;
for (auto x : e) {
int u = find(x.u), v = find(x.v);
if (u == v) continue;
fa[u] = fa[v] = ++tot;
t2.val[tot] = x.v;
g[tot].push_back(u), g[tot].push_back(v);
}
t2.dfs(tot);
vector<int> r(n + 1);
for (int i = 1; i <= n; i++) r[t1.rev[i]] = i;
for (int i = 1; i <= n; i++) upd(rt[i], rt[i - 1], 1, n, r[t2.rev[i]]);
for (int i = 0; i < q; i++) {
int s = read(), t = read(), l = read(), r = read();
++s, ++t, ++l, ++r;
int u = t1.getu(s, l), v = t2.getv(t, r);
if (qry(rt[t2.L[v] - 1], rt[t2.R[v]], t1.L[u], t1.R[u], 1, n))
puts("1");
else
puts("0");
}
return 0;
}
[IOI2018] werewolf 狼人 [kruskal重构树+主席树]的更多相关文章
- [IOI2018] werewolf 狼人 kruskal重构树,主席树
[IOI2018] werewolf 狼人 LG传送门 kruskal重构树好题. 日常安利博客文章 这题需要搞两棵重构树出来,这两棵重构树和我们平时见过的重构树有点不同(据说叫做点权重构树?),根据 ...
- 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][ ...
随机推荐
- 终于知道为什么linux文件系统权限是124了
哈哈,恍然大悟,出自pythonweb开发实战这一本书135页,有兴趣的朋友可以去了解下!
- Docker应用部署实录(包含完善Docker安装步骤)
Docker应用部署实录(包含完善Docker安装步骤) 前言 首先说一下这篇文章的来源.我之前接手的一个IOT项目,需要安装多个中控服务器.中控服务器需要安装RabbitMQ,Mysql,多个服务, ...
- 命令行开启WIFI
netsh wlan set hostednetwork allow //netsh wlan set hostednetwork mode=disallow netsh wlan set hos ...
- 视觉slam十四讲课后习题ch3--5题
题目回顾: 假设有一个大的Eigen矩阵,我想把它的左上角3x3块提取出来,然后赋值为I3x3.编程实现.解:提取大矩阵左上角3x3矩阵,有两种方式: 1.直接从0-2循环遍历大矩阵的前三行和三列 2 ...
- 剑指offer刷题笔记
删除链表中重复的结点:较难 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4- ...
- UVA5913 Dictionary Sizes(字典树)(转载)
题目大意:给出n个旧单词,要从这n个旧单词中构造新单词.构造条件是 S = Sa + Sb,其中Sa为某个旧单词的非空前缀,Sb为某个单词的非空后缀.求所有的新单词和旧单词中有多少个不同的单词. 思路 ...
- 强烈推荐 10 款珍藏的 Chrome 浏览器插件
Firebug 的年代,我是火狐(Mozilla Firefox)浏览器的死忠:但后来不知道为什么,该插件停止了开发,导致我不得不寻求一个新的网页开发工具.那段时间,不少人开始推荐 Chrome 浏览 ...
- PBFT算法java实现
PBFT 算法的java实现(上) 在这篇博客中,我会通过Java 去实现PBFT中结点的加入,以及认证.其中使用socket实现网络信息传输. 关于PBFT算法的一些介绍,大家可以去看一看网上的博客 ...
- 博客圆美化主题推荐之Slience
博客圆美化主题推荐之Slience 一.前言 本博客美化主题作者为:Esofar,本文仅在教导如何快速把该美化主题应用到自己的博客中,详细部署内容见Silence - 专注于阅读的博客园主题. 二.博 ...
- Pycrypto与RSA密码技术
密码与通信 密码技术是一门历史悠久的技术.信息传播离不开加密与解密.密码技术的用途主要源于两个方面,加密/解密和签名/验签. pip install pycrypto RSA 密码算法与 ...