简述题意 给你N个数对 表示坐标与状态(0/1), M个操作,给定一个区间,区间内的坐标的状态翻转
思路:看到区间修改,很容易想到差分,对数对sort,每个a_i与a_i-1异或构造差分数组b,每次对[l,r]区间操作时,只需要将b[l]与b[r+1]对1异或操作就行了
那么我们如何判断哪些操作需要选择呢,我们可以将每一段有关联的区间操作连边建树,我们知道,当某个点为1时,要异或为0必须操作奇数次,统计每一组操作中差分数组为1的情况,如果有偶数个差分数组为1的情况,那么一定能使每个点变为0,因为每次操作能且只能操作2个点,2个点配对为一组
那我们如何建呢,用并查集建一个生成树,统计每一棵树上的个数到树根上,这样判断树根就可以判断是否有解
如果有解,那我们从每一个树根出发跑dfs,对每个点,如果其子树(包括自己)的差分数组为1的个数为奇数,那么该点就必须进行一次操作,将他与他的父节点转变一次,使得其子树的差分数组为1的个数为偶数,那么必定通过操作将每个点化为0,有点类似点分治找重心的过程,使用后序操作,保证每一个点最后都是0,因为每个点的siz为奇数的话,其子树节点已经全为0,他自身就需要改变,siz为偶数的话,他就是一个与其他奇数节点配对的点,不需要改变,或者说他是配对的1,也就是不需要操作,举个小例子,1-1 0-1,第一个的前驱不需要改变,第二个的需要
#include<bits/stdc++.h> using namespace std; #define lowbit(x) ((x)&(-x)) typedef pair<int, int> pii; typedef long long LL; const int maxm = 1e5+5; vector<pii> G[maxm]; vector<int> ans; pii a[maxm]; int b[maxm], pos[maxm], cnt[maxm], siz[maxm], fa[maxm]; int Find(int x) { return fa[x] == x?x:fa[x] = Find(fa[x]); } void dfs(int u, int fa, int id) { siz[u] = b[u]; for(auto i : G[u]) { int v = i.first; if(v == fa) continue; dfs(v, u, i.second); siz[u] += siz[v]; } if(siz[u] & 1) ans.push_back(id); } void run_case() { int n, m; cin >> n >> m; for(int i = 1; i <= n; ++i) cin >> a[i].first >> a[i].second; sort(a+1, a+1+n); for(int i = 1; i <= n; ++i) pos[i] = a[i].first; for(int i = 1; i <= n+1; ++i) { fa[i] = i; b[i] = a[i].second ^ a[i-1].second; } for(int i = 1; i <= m; ++i) { int l, r, tl, tr; cin >> l >> r; l = lower_bound(pos+1, pos+1+n, l) - pos; r = upper_bound(pos+1, pos+1+n, r) - pos; tl = Find(l), tr = Find(r); if(tl == tr) continue; fa[tl] = tr; G[l].push_back(make_pair(r, i)); G[r].push_back(make_pair(l, i)); } for(int i = 1; i <= n+1; ++i) if(b[i]) cnt[Find(i)]++; for(int i = 1; i <= n+1; ++i) if(Find(i) == i && (cnt[i]&1)) { cout << "-1"; return; } for(int i = 1; i <= n+1; ++i) { if(Find(i) == i) dfs(i, 0, 0); } sort(ans.begin(), ans.end()); cout << ans.size() << " "; for(auto i : ans) cout << i << " "; } int main() { ios::sync_with_stdio(false), cin.tie(0); //cout.setf(ios_base::showpoint);cout.precision(8); run_case(); cout.flush(); return 0; }