bzoj3237: [Ahoi2013]连通图

上线段树分治

它删除的边的总数不会很大,我们可以维护一条边在那一段时间里面是存在的

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

struct edge{int x,y;}e[410000];

struct trnode
{
    int l,r,lc,rc;
    vector<int>id;
}tr[410000];int trlen;
void bt(int l,int r)
{
    int now=++trlen;
    tr[now].l=l;tr[now].r=r;
    tr[now].lc=tr[now].rc=-1;
    if(l<r)
    {
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
    }
}
void change(int now,int l,int r,int p)
{
    if(tr[now].l==l&&tr[now].r==r)
    {
        tr[now].id.push_back(p);
        return ;
    }
    int mid=(tr[now].l+tr[now].r)/2;
    int lc=tr[now].lc,rc=tr[now].rc;
           if(r<=mid)  change(lc,l,r,p);
    else if(mid+1<=l)change(rc,l,r,p);
    else change(lc,l,mid,p),change(rc,mid+1,r,p);
}

int n,cnt,fa[410000];
int findfa(int x)
{
    if(fa[x]<0)return x;
    return findfa(fa[x]);
}
struct Clear
{
    int fx,fy,dx,dy,id;
    Clear(){}
    Clear(int FX,int FY,int DX,int DY,int ID){fx=FX,fy=FY,dx=DX,dy=DY,id=ID;}
}sta[410000];int top;
void merge(int now,int x,int y)
{
    int fx=findfa(x),fy=findfa(y);
    if(fx!=fy)
    {
        cnt++;
        sta[++top]=Clear(fx,fy,fa[fx],fa[fy],now);
        if(fa[fx]<fa[fy])
            fa[fx]+=fa[fy],fa[fy]=fx;
        else
            fa[fy]+=fa[fx],fa[fx]=fy;
    }
}
void sprit(int p)
{
    cnt--;
    fa[sta[p].fx]=sta[p].dx;
    fa[sta[p].fy]=sta[p].dy;
}

bool as[410000];
void dfs(int now)
{
    for(int i=0;i<tr[now].id.size();i++)
        merge(now,e[tr[now].id[i]].x,e[tr[now].id[i]].y);
        
    if(cnt==n-1)
    {
        for(int i=tr[now].l;i<=tr[now].r;i++)as[i]=true;
    }
    else if(tr[now].l==tr[now].r);
    else
    {
        dfs(tr[now].lc);
        dfs(tr[now].rc);
    }
    
    while(sta[top].id==now)
        sprit(top--);
}

int las[410000];
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    int m,x,y;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%d%d",&e[i].x,&e[i].y);
    
    for(int i=1;i<=m;i++)las[i]=1;
    int Q,S;
    scanf("%d",&Q);
    trlen=0;bt(1,Q);
    for(int q=1;q<=Q;q++)
    {
        scanf("%d",&S);
        for(int i=1;i<=S;i++)
        {
            scanf("%d",&x);
            if(las[x]<=q-1)
            {
                change(1,las[x],q-1,x);
            //    printf("%d %d %d\n",x,las[x],q-1);
            }
            las[x]=q+1;
        }
    }
    for(int i=1;i<=m;i++)
        if(las[i]<=Q)
        {
            change(1,las[i],Q,i);
        //    printf("%d %d %d\n",i,las[i],Q);
        }
        
    for(int i=1;i<=m;i++)fa[i]=-1;
    cnt=top=0;dfs(1);
    for(int i=1;i<=Q;i++)
        if(as[i])printf("Connected\n");
        else printf("Disconnected\n");
            
    return 0;
}

 

posted @ 2019-01-03 07:53  AKCqhzdy  阅读(148)  评论(0编辑  收藏  举报