Problem :
給一個2×n的矩陣,一開始矩陣全部相鄰點之間有一條邊。有其、個詢問,每次給出兩個相鄰的點的座標,將其中的邊刪除或者添加,問如此操做以後整張圖的割邊數量。
, q<=2*10^5, 圖始終保證聯通。
Solution :
首先能夠發現不能成爲割邊的邊,必定被某個環所包含。所以只要維護每一個環的大小便可。
若某條橫邊在兩行中均出現了兩次,纔有可能構成環。用set來維護全部連續的橫邊。再用線段樹來維護全部豎邊的位置。
計算一條連續的橫邊產生的不能成爲割邊的數量,統計其中最左和最右的豎邊以及豎邊的數量就好了。php
#include <bits/stdc++.h> using namespace std; const int N = 2e5 + 8; const int INF = 1e9 + 7; #define endl "\n" #define y1 qqq struct node { int l, r; node(){} node(int l, int r):l(l),r(r){} bool operator < (const node &b) const { return l < b.l; } }; multiset <node> S; int n, q, mtot, num; int cnt[N]; class Segment_Tree { public: int tagmin[N << 2], tagmax[N << 2], tagsum[N << 2]; void pushup(int rt) { tagmin[rt] = min(tagmin[rt << 1], tagmin[rt << 1 | 1]); tagmax[rt] = max(tagmax[rt << 1], tagmax[rt << 1 | 1]); tagsum[rt] = tagsum[rt << 1] + tagsum[rt << 1 | 1]; } void build(int l, int r, int rt) { tagmin[rt] = INF; tagmax[rt] = 0; tagsum[rt] = 0; if (l == r) { tagmin[rt] = tagmax[rt] = l; tagsum[rt] = 1; return; } int m = l + r >> 1; build(l, m, rt << 1); build(m + 1, r, rt << 1 | 1); pushup(rt); } void update(int x, int op, int l, int r, int rt) { if (l == r) { if (op == 1) { tagmin[rt] = tagmax[rt] = l; tagsum[rt] = 1; } else { tagmin[rt] = INF; tagmax[rt] = 0; tagsum[rt] = 0; } return; } int m = l + r >> 1; if (x <= m) update(x, op, l, m, rt << 1); else update(x, op, m + 1, r, rt << 1 | 1); pushup(rt); } void querymax(int L, int R, int l, int r, int rt, int &ans) { if (L <= l && r <= R) { ans = max(ans, tagmax[rt]); return; } int m = l + r >> 1; if (L <= m) querymax(L, R, l, m, rt << 1, ans); if (m < R) querymax(L, R, m + 1, r, rt << 1 | 1, ans); } void querymin(int L, int R, int l, int r, int rt, int &ans) { if (L <= l && r <= R) { ans = min(ans, tagmin[rt]); return; } int m = l + r >> 1; if (L <= m) querymin(L, R, l, m, rt << 1, ans); if (m < R) querymin(L, R, m + 1, r, rt << 1 | 1, ans); } void querysum(int L, int R, int l, int r, int rt, int &ans) { if (L <= l && r <= R) { ans += tagsum[rt]; return; } int m = l + r >> 1; if (L <= m) querysum(L, R, l, m, rt << 1, ans); if (m < R) querysum(L, R, m + 1, r, rt << 1 | 1, ans); } }T; int calc(int l, int r) { int L = INF, R = -INF, sum = 0; T.querymin(l, r, 1, n, 1, L); T.querymax(l, r, 1, n, 1, R); T.querysum(l, r, 1, n, 1, sum); if (sum <= 1) return 0; return (R - L) * 2 + sum; } void init() { cin >> n >> q; T.build(1, n, 1); S.clear(); for (int i = 1; i <= n; ++i) cnt[i] = 2; S.insert(node(1, n)); S.insert(node(-1, -1)); S.insert(node(n + 2, n + 2)); mtot = 3 * n - 2; num = calc(1, n); } void work_row_add(int x) { auto l = S.upper_bound(node(x, x + 1)); l--; auto r = S.lower_bound(node(x, x + 1)); cnt[x]++; mtot++; if (cnt[x] == 1) { cout << mtot - num << endl; return; } if (l->r == x && r->l == x + 1) { num -= calc(l->l, l->r); num -= calc(r->l, r->r); num += calc(l->l, r->r); S.insert(node(l->l, r->r)); S.erase(l); S.erase(r); } else if (l->r == x && r->l != x + 1) { num -= calc(l->l, l->r); num += calc(l->l, x + 1); S.insert(node(l->l, x + 1)); S.erase(l); } else if (l->r != x && r->l == x + 1) { num -= calc(r->l, r->r); num += calc(x, r->r); S.insert(node(x, r->r)); S.erase(r); } else if (l->r != x && r->l != x + 1) { num += calc(x, x + 1); S.insert(node(x, x + 1)); } } void work_row_del(int x) { auto p = S.upper_bound(node(x, x + 1)); p--; cnt[x]--; mtot--; if (cnt[x] == 0) return; if (p->l == x && p->r == x + 1) { num -= calc(x, x + 1); S.erase(p); } else if (p->l == x && p->r != x + 1) { num += calc(x+1,p->r); num -= calc(p->l,p->r); S.insert(node(x+1,p->r)); S.erase(p); } else if (p->l != x && p->r == x + 1) { num += calc(p->l,x); num -= calc(p->l,p->r); S.insert(node(p->l,x)); S.erase(p); } else if (p->l != x && p->r != x + 1) { num -= calc(p->l, p->r); num += calc(p->l, x); num += calc(x+1, p->r); S.insert(node(p->l, x)); S.insert(node(x+1, p->r)); S.erase(p); } } void work_col_add(int x) { auto p = S.upper_bound(node(x, x)); p--; mtot++; if (p->r >= x) { num -= calc(p->l, p->r); T.update(x, 1, 1, n, 1); num += calc(p->l, p->r); } else { T.update(x, 1, 1, n, 1); } } void work_col_del(int x) { auto p = S.upper_bound(node(x, x)); p--; mtot--; if (p->r >= x) { num -= calc(p->l, p->r); T.update(x, -1, 1, n, 1); num += calc(p->l, p->r); } else { T.update(x, -1, 1, n, 1); } } void solve() { for (; q; --q) { int op, x1, y1, x2, y2; cin >> op >> x1 >> y1 >> x2 >> y2; if (y1 > y2) swap(y1, y2); if (op == 1) if (x1 == x2) work_row_add(y1); else work_col_add(y1); else if (x1 == x2) work_row_del(y1); else work_col_del(y1); cout << mtot - num << endl; } } int main() { cin.sync_with_stdio(0); int T; cin >> T; for (int cas = 1; cas <= T; ++cas) { init(); solve(); } }