1. 程式人生 > >[SHOI2008]堵塞的交通 - 題解

[SHOI2008]堵塞的交通 - 題解

在校網上做題時發現原題QwQ……

題解:

這很明顯是求動態圖的連通性啊,果斷線段樹分治。

線段樹分治就是按時間進行分治,利用按秩合併的並查集合並/分離操作維護連通性,LOJ似乎有一道非常好的模板題:「離線可過」動態圖連通性

剩下的就是粘板子了,儲存邊時用map維護即可。

時間複雜度 \(O(m log m)\)(m為運算元)。

程式碼:

#include<bits/stdc++.h>
using namespace std;
int n,m=0;
struct T { int l,r;vector <int> id; };T t[400010];
struct P { int opt,x,y; };P q[100010];
struct S { int x,dep; };S sta[400010];
map <int,int> ma[200010];
char s[10];
int fa[200010],dep[200010],top=0;

inline int Max(int x,int y) { return x>y?   x:y; }
void build(int u,int l,int r) {
    t[u].l=l,t[u].r=r; if(l>=r) return ;
    int mid=(l+r)>>1; build(u*2,l,mid),build(u*2+1,mid+1,r);
}
void ins(int u,int l,int r,int w) {
    if(l==t[u].l&&r==t[u].r) { t[u].id.push_back(w);return ; }
    int mid=(t[u].l+t[u].r)>>1;
    if(r<=mid)  ins(u*2,l,r,w); else if(l>mid)  ins(u*2+1,l,r,w);
    else    ins(u*2,l,mid,w),ins(u*2+1,mid+1,r,w);
}
inline int find(int x) { return x==fa[x]?   x:find(fa[x]); }
void Union(int x,int y) {
    x=find(x),y=find(y); if(x==y)   return ;
    if(dep[x]<dep[y])   x^=y,y^=x,x^=y;
    fa[y]=x;sta[++top]=(S){y,dep[y]},sta[++top]=(S){x,dep[x]};
    dep[x]=Max(dep[x],dep[y]+1);
}
void dfs(int u) {
    int Now=top;
    for(int i=0;i<t[u].id.size();i++)   Union(q[t[u].id[i]].x,q[t[u].id[i]].y);
    if(t[u].l>=t[u].r) {
        if(q[t[u].l].opt==3)
            find(q[t[u].l].x)==find(q[t[u].l].y)?   puts("Y"):puts("N");
        return ;
    }
    dfs(u*2),dfs(u*2+1);
    while(top>Now)  fa[sta[top].x]=sta[top].x,dep[sta[top].x]=sta[top].dep,--top;
}
int main() {
    scanf("%d",&n),build(1,1,100000);
    for(int i=1;i<=n+n;i++) fa[i]=i,dep[i]=1;
    for(int i=1;;++i) {
        scanf("%s",s); if(s[0]=='E')    break;
        int a,b,c,d,x,y; ++m;
        scanf("%d%d%d%d",&a,&b,&c,&d),x=(a-1)*n+b,y=(c-1)*n+d;
        if(x>y) x^=y,y^=x,x^=y;
        q[m].x=x,q[m].y=y;
        if(s[0]=='O')   q[m].opt=1,ma[x][y]=i;
        else if(s[0]=='C')
            ins(1,ma[x][y],i-1,i),ma[x].erase(ma[x].find(y)),q[m].opt=2;
        else    q[m].opt=3;
    }
    for(int i=1;i<=n+n;i++)
        for(map<int,int>::iterator it=ma[i].begin();it!=ma[i].end();++it)
            ins(1,it->second,m,it->second);
    dfs(1);
    return 0;
}