# BZOJ4025: 二分图【线段树分治】【带撤销的并查集】

3 3 3
1 2 0 2
2 3 0 3
1 3 1 2

Yes
No
Yes

### HINT

0时刻，出现两条边1-2和2-3。

1时刻，出现一条边1-3。

2时刻，1-2和1-3两条边消失。

n<=100000，m<=200000，T<=100000，1<=u,v<=n，0<=start<=end<=T。

• dfs的时候就算到达了叶节点别忘了删除加入的边

• 并查集合并需要启发式的，并且需要用异或值来维护路径奇偶性

然后如果当前加入边，一定要保证$(u,v)$距离是奇数，所以用异或计算一下合并根节点的距离

• 注意清空dep这个数组

//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
template <typename T>
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 2e5 + 10;
#define mp make_pair
#define fi first
#define se second
typedef pair<int, int> pi;
typedef pair<pi, pi> pii;

#define LD (t << 1)
#define RD (t << 1 | 1)
vector<pi> g[N << 2];

void modify(int t, int l, int r, int ql, int qr, pi edge) {
if (ql <= l && r <= qr) {
g[t].push_back(edge);
return;
}
int mid = (l + r) >> 1;
if (qr <= mid) modify(LD, l, mid, ql, qr, edge);
else if (ql > mid) modify(RD, mid + 1, r, ql, qr, edge);
else {
modify(LD, l, mid, ql, mid, edge);
modify(RD, mid + 1, r, mid + 1, qr, edge);
}
}

stack<pair<pii, pi> > st;
int dep[N], height[N], fa[N];
int ans = 1;

int Find(int x) {
if (x == fa[x]) return x;
return Find(fa[x]);
}

int Getdep(int x) {
if (x == fa[x]) return 0;
return dep[x] ^ Getdep(fa[x]);
}

void Merge(int u, int v) {
int fau = Find(u), fav = Find(v);
st.push(mp(mp(mp(fau, fav), mp(height[fau], height[fav])), mp(ans, fau != fav)));
int w = Getdep(u) ^ Getdep(v);
if (fau == fav) {
if (!(w & 1)) ans = 0;
return;
}
if (height[fau] == height[fav]) {
fa[fav] = fau;
dep[fav] = w ^ 1;
++height[fau];
} else if (height[fau] > height[fav]) {
fa[fav] = fau;
dep[fav] = w ^ 1;
} else {
fa[fau] = fav;
dep[fau] = w ^ 1;
}
}

void Delete() {
pair<pii, pi> now = st.top(); st.pop();
ans = now.se.fi;
if (!now.se.se) return;
int u = now.fi.fi.fi, heightu = now.fi.se.fi;
int v = now.fi.fi.se, heightv = now.fi.se.se;
if (heightu == heightv) {
fa[v] = v;
dep[v] = 0;
--height[u];
} else if (heightu > heightv) {
fa[v] = v;
dep[v] = 0;
} else {
fa[u] = u;
dep[u] = 0;
}
}

void dfs(int t, int l, int r) {
fv(i, g[t]) Merge(g[t][i].fi, g[t][i].se);
if (!ans) {
fu(i, l, r) printf("No\n");
} else {
if (l == r) {
printf("Yes\n");
} else {
int mid = (l + r) >> 1;
dfs(LD, l, mid);
dfs(RD, mid + 1, r);
}
}
fv(i, g[t]) Delete();
}

int n, m, T;
int main() {
freopen("input.txt", "r", stdin);