P5787 二分图 /【模板】线段树分治
2024-10-21 11:52:49
\(\text{Solution}\)
线段树分治的模板
对时间分治,线段树下标表示时间
在线段树上处理每条覆盖当前区间的边,对当前的时间区间求答案
小区间的信息可以由大区间一路下来得到,那么答案就是叶子节点的答案
对于二分图的加边动态判定,可以用并查集维护
具体来说就是用带权并查集,维护每个点与其父亲点集的异同
因为线段树区间返回时需要撤销并查集操作,那么就打个可撤销并查集按秩合并即可
\(\text{Code}\)
#include <cstdio>
#include <iostream>
#define re register
#define ls (p << 1)
#define rs (ls | 1)
using namespace std;
const int N = 2e5 + 5;
int n, m, k, tot, top;
struct node{
int x, y;
inline node(int u = 0, int v = 0){x = u, y = v;}
}e[N];
int Q[N << 2];
struct edge{
int nxt, to;
inline edge(int x = 0, int y = 0){nxt = x, to = y;}
}E[N * 21];
struct stack{
int x, y;
inline stack(int u = 0, int v = 0){x = u, y = v;}
}stk[N * 21];
inline void read(int &x)
{
x = 0; char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
}
void update(int p, int l, int r, int tl, int tr, int x)
{
if (tl <= l && r <= tr)
{
E[++tot] = edge(Q[p], x), Q[p] = tot;
return;
}
int mid = (l + r) >> 1;
if (tl <= mid) update(ls, l, mid, tl, tr, x);
if (tr > mid) update(rs, mid + 1, r, tl, tr, x);
}
int fa[N], siz[N], d[N], ans[N];
int find(int x){return (fa[x] == x ? x : find(fa[x]));}
int getdis(int x)
{
if (x == fa[x]) return d[x];
return d[x] ^ getdis(fa[x]);
}
void solve(int p, int l, int r)
{
int lst = top, flag = 0, mid = (l + r) >> 1;
for(re int i = Q[p], x, y, u, v; i; i = E[i].nxt)
{
x = e[E[i].to].x, y = e[E[i].to].y, u = find(x), v = find(y);
if (u ^ v)
{
if (siz[u] > siz[v]) swap(u, v), swap(x, y);
fa[u] = fa[v], d[u] = d[x] ^ d[y] ^ 1, siz[v] += siz[u];
stk[++top] = stack(u, v);
}
else if (!(getdis(x) ^ getdis(y))){flag = 1; break;}
}
if (flag ^ 1)
if (l ^ r) solve(ls, l, mid), solve(rs, mid + 1, r);
else ans[l] = 1;
for(int x, y; lst ^ top; --top)
x = stk[top].x, y = stk[top].y, fa[x] = x, d[x] = 0, siz[y] -= siz[x];
}
int main()
{
read(n), read(m), read(k);
for(re int i = 1, l, r, x, y; i <= m; i++)
read(x), read(y), read(l), read(r), ++l, ++r, e[i] = node(x, y), update(1, 1, n, l, r - 1, i);
for(re int i = 1; i <= n; i++) fa[i] = i, siz[i] = 1;
solve(1, 1, k);
for(re int i = 1; i <= k; i++) (ans[i] ? printf("Yes\n") : printf("No\n"));
}
最新文章
- json数据格式及json校验格式化工具简单实现
- Win7下VS2008破解方法
- Lisp 函数
- [BS-28] iOS中分页的几种算法
- tp-link便携式路由器固件升级方式
- Codeforces Round #FF/#255 D DZY Loves Modification --贪心+优先队列
- 03.Hibernate一对多关联
- PHP用反撇号(`,也就是键盘上ESC键下面的那个,和~在同一个上面)执行外部命令
- JqueryEasyUI 增加选项卡
- # Day04-Android
- google base 之MessagePumpForUI
- ubuntu 使用第一天
- 【】小技巧】CSS文字两端对齐
- Janus 二元神漏洞测试
- EM算法的直观描述
- PAT1097:Deduplication on a Linked List
- mybatis小结
- 前端入门14-JavaScript进阶之继承
- Linux - DDOS检测
- plsql 查询 卡死问题解决