题意:

当你是人形的时候你只能走 \([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;
}

最新文章

  1. PHP类与面向对象(二)
  2. &lt;转&gt;2015-7-14面试题
  3. 微软TechEd2013大会门票热卖!
  4. 基于JavaScript的REST客户端框架
  5. MVC常用 ActionResult
  6. 继续完成昨天的第一个点:更改DJANGO的ADMIN后台的表单显示
  7. FM笔记
  8. float
  9. 【使用Itext处理PDF文档(新建PDF文件、修改PDF文件、PDF中插入图片、将PDF文件转换为图片)】
  10. Java 小记 — Spring Boot 的实践与思考
  11. mysql命令行下创建数据库,创建表,插入数据,查询数据
  12. AI之旅(6):神经网络之前向传播
  13. Java_解惑
  14. 10.31vue(一)
  15. C# unicode 转中文
  16. 【php 之获得当前日期以及比较日期大小】
  17. sgu187&amp;&amp;spoj7734
  18. hbase表的多版本读写
  19. Django配置参数可选总结
  20. JS如何判断浏览器类型,如何模拟浏览器类型(模拟微信浏览器)

热门文章

  1. Shell之用户与权限
  2. Leetcode 题目整理-5 Valid Parentheses &amp; Merge Two Sorted Lists
  3. Maven: 每次更新Maven Project ,JAVA 版本都变为1.5
  4. 如何快速查看Linux日志?
  5. 使用Java注解实现简单的依赖注入
  6. ARTS Week 15
  7. 用python制作训练集和测试集的图片名列表文本
  8. BZOJ 2733 [HNOI2012]永无乡 (权值线段树启发式合并+并查集)
  9. To be contine ,NW NMM backup sqlserver failed.
  10. Ansible:roles初始化系统