P4246 [SHOI2008]堵塞的交通

思路

同LOJ121
动态图连通性的板子
好像有很神的线段树做法,不会,先码住

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <map>
#include <set>
#include <vector>
using namespace std;
const int MAXN = 100100;
int c,n,time,ans[MAXN],anscnt;
char s[MAXN];
inline int id(int rr,int cc){
    return (rr-1)*c+cc;
}
struct uDSU{
    int h[MAXN],fa[MAXN];
    stack<int> height,mer;
    int find(int x){
        if(x==fa[x])
            return x;
        else
            return find(fa[x]);
    }
    void merge(int x,int y){
       x=find(x);
       y=find(y);
       if(h[x]<=h[y]){
            fa[x]=y;
            mer.push(x);
            if(h[x]==h[y]){
                h[y]++;
                height.push(1);
            }
            else{
                height.push(0);
            }
       }
       else{
            fa[y]=x;
            mer.push(y);
            height.push(0);
       }
    }
    bool query(int x,int y){
        return find(x)==find(y);
    }
    void undo(void){
        int val=height.top();
        height.pop();
        int x=mer.top();
        mer.pop();
        h[fa[x]]-=val;
        fa[x]=x;
    }
    void init(void){
        for(int i=1;i<=n;i++)
            h[i]=1,fa[i]=i;
    }
}DSU;
map<pair<int,int>,int > M;
struct Node{
    int le,u,v;
    bool operator < (const Node &b) const{
        return le<b.le;
    }
};
vector<Node> seg[MAXN<<2];
void add(int L,int R,int l,int r,int o,int le,int u,int v){
    if(L<=l&&r<=R){
        seg[o].push_back((Node){le,u,v});
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid)
        add(L,R,l,mid,o<<1,le,u,v);
    if(R>mid)
        add(L,R,mid+1,r,o<<1|1,le,u,v);
}
void dfs(int o,int l,int r){
    sort(seg[o].begin(),seg[o].end());
    for(int i=0;i<seg[o].size();i++)
        if(seg[o][i].le==-1)
            DSU.merge(seg[o][i].u,seg[o][i].v);
        else
            ans[seg[o][i].le]=DSU.query(seg[o][i].u,seg[o][i].v);
    if(l!=r){
        int mid=(l+r)>>1;
        dfs(o<<1,l,mid);
        dfs(o<<1|1,mid+1,r);
    }
    for(int i=0;i<seg[o].size();i++)
        if(seg[o][i].le==-1)
            DSU.undo();
}
int main(){
    scanf("%d",&c);
    n=c*2;
    DSU.init();
    scanf("%s",s);
    while(s[0]!='E'){
        ++time;
        int r1,c1,r2,c2;
        scanf("%d %d %d %d",&r1,&c1,&r2,&c2);
        int x=id(r1,c1),y=id(r2,c2);
        if(x>y)
            swap(x,y);
        if(s[0]=='C'){
            add(M[make_pair(x,y)],time,1,100010,1,-1,x,y);
            M.erase(make_pair(x,y));
        }
        if(s[0]=='O'){
            M[make_pair(x,y)]=time;
        }
        if(s[0]=='A'){
            add(time,time,1,100010,1,++anscnt,x,y);
        }
        scanf("%s",s);
    }
    ++time;
    for(map<pair<int,int>,int >::iterator it=M.begin();it!=M.end();it++)
        add((*it).second,time,1,100010,1,-1,(*it).first.first,(*it).first.second);
    dfs(1,1,100010);
    for(int i=1;i<=anscnt;i++)
        printf("%s\n",(ans[i])?"Y":"N");
    return 0;
}

posted @ 2019-03-06 16:12  dreagonm  阅读(159)  评论(0编辑  收藏  举报