定义
线段树分治是一种解决一类有插入、删除和整体查询操作的问题的方法。它是一种离线做法,通过在线段树上记录操作的时间区间来处理修改对询问的影响。每个操作被看作一个时间区间的修改,并在线段树上进行标记。然后通过深度优先搜索(DFS)依次执行这些操作,直到根节点来回答查询,并在离开时将其撤销。
题目
#include <bits/stdc++.h>
#define fo(a,b,c) for(int a=b;a<=c;a++)
#define re(a,b,c) for(int a=b;a>=c;a--)
#define mod 1000000007
#define inp 10000019
using namespace std;
const int N = 500005;
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int nyn = 1;
int n, e[5005][5005], cnt, st[N], en[N], fr[N], to[N], f[N];
int op2l[N], op2r[N], sz[N], tot;
struct sss {
int x, y, szx, szy;
} sta[N];
int find(int x) {
if (f[x] == x)
return x;
return find(f[x]);
}
void merge(int x, int y) {
x = find(x);
y = find(y);
if (x == y)
return;
tot++;
if (sz[x] > sz[y])
swap(x, y);
sta[tot].x = x;
sta[tot].y = y;
sta[tot].szx = sz[x];
sta[tot].szy = sz[y];
f[x] = y;
sz[y] += sz[x];
}
void split(int k) {
while (tot > k) {
int x = sta[tot].x, y = sta[tot].y;
int szx = sta[tot].szx;
int szy = sta[tot].szy;
f[x] = x;
sz[x] = szx;
sz[y] = szy;
tot--;
}
}
struct IO {
vector<int> t;
} node[N * 4];
void ud(int rt, int l, int r, int L, int R, int val) {
if (l > r)
return;
if (L <= l && r <= R) {
node[rt].t.push_back(val);
return;
}
int mid = (l + r) / 2;
if (L <= mid)
ud(rt * 2, l, mid, L, R, val);
if (R >= mid + 1)
ud(rt * 2 + 1, mid + 1, r, L, R, val);
}
void qr(int rt, int l, int r) {
int num = tot;
for (int i = 0; i < node[rt].t.size(); i++) {
int x = node[rt].t[i];
merge(fr[x], to[x]);
}
if (l == r) {
if (l == 1)
return;
int x = op2l[l], y = op2r[l];
int fx = find(x), fy = find(y);
if (fx == fy)cout << "Y\n";
else cout << "N\n";
split(num);
return;
}
int mid = (l + r) / 2;
qr(rt * 2, l, mid);
qr(rt * 2 + 1, mid + 1, r);
split(num);
}
int dp[N];
void sol() {
n = read();
for (int i = 1; i <= n; i++)
f[i] = i, sz[i] = 1;
int m = read();
int tm = 1;
for (int i = 1; i <= m; i++) {
int op = read();
if (op == 0) {
cnt++;
int x = read();
int y = read();
fr[cnt] = x;
to[cnt] = y;
e[x][y] = e[y][x] = cnt;
st[cnt] = tm + 1;
} else if (op == 1) {
int x = read();
int y = read();
en[e[x][y]] = tm;
e[x][y] = 0;
} else {
tm++;
op2l[tm] = read();
op2r[tm] = read();
}
}
for (int i = 1; i <= cnt; i++)
if (en[i])
ud(1, 1, tm, st[i], en[i], i);
else
ud(1, 1, tm, st[i], tm, i);
qr(1, 1, tm);
}
int main() {
while (nyn--) {
sol();
printf("\n");
}
}
P5787 二分图 /【模板】线段树分治
https://www.luogu.com.cn/blog/xzc/xian-duan-shu-fen-zhi
嘻嘻,结束!