[SHOI2008]堵塞的交通traffic

这是一道毒瘤题
只要线段树维护一个矩形的四个点的连通性即可
合并时请想清楚,要大讨论一番
询问有可能存在跨区间的联通情况,只要把询问的区间分成[1,l],[l,r],[r,n]再大讨论一番即可
如果你不想讨论或者讨论出错,你可以使用并查集,每次开并查集更新,这样就不用大讨论一番了,但是会慢,时间几乎是两倍。。。
像我这种不会讨论的蒟蒻想到了后果断用并查集


自我感觉代码还是比较短的

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define ZSYbeatME 666
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(4e6 + 10), INF(2e9);

IL ll Read(){
    char c = '%'; ll x = 0, z = 1;
    for(; c > '9' || c < '0'; c = getchar()) if(c == '-') z = -1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
    return x * z;
}

int n, gg;
struct Data{
    bool ab, ac, ad, bc, bd, cd;
    IL void Init(){  ab = ac = ad = bc = bd = cd = 0;  }
} t[_], f[_];
int fa[4];

IL int Find(RG int x){  return fa[x] == x ? x : fa[x] = Find(fa[x]);  }

IL void Link(RG int x, RG int y){  if(Find(x) != Find(y)) fa[Find(x)] = Find(y);  }

IL bool OK(RG int x, RG int y){  return Find(x) == Find(y);  }

IL void Update(RG Data &A){
    for(RG int i = 0; i < 4; i++) fa[i] = i;
    if(A.ab) Link(0, 1); if(A.ac) Link(0, 2);
    if(A.ad) Link(0, 3); if(A.bc) Link(1, 2);
    if(A.bd) Link(1, 3); if(A.cd) Link(2, 3);
    A.ab = OK(0, 1); A.ac = OK(0, 2);
    A.ad = OK(0, 3); A.bc = OK(1, 2);
    A.bd = OK(1, 3); A.cd = OK(2, 3);
}

IL Data Merge(RG Data A, RG Data B){
    RG Data C;
    C.ab = A.ab | (A.ad & A.bc & B.ab);
    C.cd = B.cd | (B.ad & B.bc & A.cd);
    C.ac = (A.ac & B.bc) | (A.ad & B.ac);
    C.ad = (A.ad & B.ad) | (A.ac & B.bd);
    C.bc = (A.bc & B.bc) | (A.bd & B.ac);
    C.bd = (A.bd & B.ad) | (A.bc & B.bd);
    Update(C);
    return C;
}

IL void Modify(RG int x, RG int l, RG int r, RG int id, RG int d, RG bool v){
    if(id < l || id > r) return;
    if(l == r){
        if(d == 0) f[x].ab = v;
        else if(d == 1) f[x].cd = v;
        else if(d == 2) f[x].ad = v;
        else f[x].bc = v;
        t[x] = f[x]; Update(t[x]);
        return;
    }
    RG int mid = (l + r) >> 1;
    if(id <= mid) Modify(x << 1, l, mid, id, d, v);
    else Modify(x << 1 | 1, mid + 1, r, id, d, v);
    t[x] = Merge(t[x << 1], t[x << 1 | 1]);
}

IL Data Query(RG int x, RG int l, RG int r, RG int L, RG int R){
    RG Data ans; ans.Init();
    if(L > R) return ans;
    if(L <= l && R >= r) return t[x];
    RG int mid = (l + r) >> 1;
    if(R <= mid) return Query(x << 1, l, mid, L, R);
    if(L > mid) return Query(x << 1 | 1, mid + 1, r, L, R);
    ans = Merge(Query(x << 1, l, mid, L, R), Query(x << 1 | 1, mid + 1, r, L, R));
    return ans;
}

IL bool Calc(RG int a, RG int b, RG int c, RG int d){
    RG Data A = Query(1, 1, n, 1, b - 1), B, C = Query(1, 1, n, d, n);
    if(b == d) return A.cd | C.ab;
    B = Query(1, 1, n, b, d - 1);
    B.ab |= A.cd; B.cd |= C.ab; Update(B);
    if(a == 1 && c == 2) return B.ac;
    if(a == 1 && c == 1) return B.ad;
    if(a == 2 && c == 1) return B.bd;
    if(a == 2 && c == 2) return B.bc;
}

int main(RG int argc, RG char *argv[]){
    n = Read() - 1; RG char op[10]; RG int a, b, c, d;
    while(ZSYbeatME){
        scanf(" %s", op); if(op[0] == 'E') break;
        a = Read(); b = Read(); c = Read(); d = Read();
        if(b > d) swap(a, c), swap(b, d);
        if(op[0] == 'A') puts(Calc(a, b, c, d) ? "Y" : "N");
        else{
            RG int opt = op[0] == 'O';
            if(b == d) Modify(1, 1, n, b, 0, opt), Modify(1, 1, n, b - 1, 1, opt);
            else Modify(1, 1, n, b, a + 1, opt);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cjoieryl/p/8206335.html