3988: 地理课(geography)

题目描述

 

地理课上,老师给出了一个巨大的地图,由于世界日新月异,会有一些道路在某一时刻被删除,也会有一些道路在某一时刻被修建。这里的道路均为双向的。

老师认为,有一些城市被分在了一个连通块中可以相互到达,而有一些城市不能够相互到达。而他想知道,每个时刻所有连通块大小的乘积是多少?

wzy看到这个地图的时候就蒙了,还好那只上天的喵及时帮助了他。现在他把这个毒瘤的地图拿过来给你,想试试看你能不能求出来。由于答案可能很大,输出乘积mod109+7mod109+7即可。

 

 

输入

 

第一行两个数n,mn,m,表示有nn个点,mm个时刻。接下来mm行每行三个数,要么是1uv1uv,要么是2uv2uv,分别表示添加一条无向边和删除一条无向边。

 

 

输出

 

共mm,每行一个数表示连通块大小乘积mod1,000,000,007mod1,000,000,007

 

 

样例输入

样例输入#1
5 6
1 1 3
1 2 3
1 1 2
1 4 5
1 3 4
2 3 4
样例输入#2(对应subtask1)
见example\geography\geography2.in
样例输入#3(对应subtask2)
见example\geography\geography3.in

样例输出

样例输出#1
2
3
3
6
5
6
样例输出#2
见example\geography\geography2.out
样例输出#3
见example\geography\geography3.out

提示

 

 

上面是每个时刻操作后的图。乘积分别为:

2*1*1*1=2,3*1*1=3,3*1*1=3,3*2=6,5,3*2=6

数据范围及约定

subtask1:30pts,n≤1,000,m≤2,000n≤1,000,m≤2,000

subtask2:20pts,满足没有删除操作。

subtask3:50pts,n,m≤100,000n,m≤100,000保证没有重边自环,不会删除不存在的边。

 

题解:每一条边都会存在一段时间,所以我们可以给每一条边一个编号,在线段树上进行覆盖。

而答案就是每一个叶子结点的答案。

所以我们可以用可退还的并查集统计答案。

#include
#include
#include
#include
#include
#define mod 1000000007
using namespace std;
typedef long long ll;
struct Node{int opt,x,y;}s[100005];
int n,m,par[100005],si[100005],cnt,las[100005];
int prex[100005],prey[100005],top[30];
struct xx{int x,y,z;}zh[30][100005];
ll ans=1,ny[100005];
struct node
{
    int l,r;
    vectorv;
}tree[400005];
mapdy[100005];
int find(int x)
{
    if(par[x]!=x)return find(par[x]);
    return x;
}
void build(int k,int l,int r)
{
    tree[k].l=l;tree[k].r=r;
    if(l==r)return;
    int mid=l+r>>1;
    build(k*2,l,mid);build(k*2+1,mid+1,r);
}
void update(int k,int l,int r,int t)
{
    if(l<=tree[k].l&&r>=tree[k].r){tree[k].v.push_back(t);return;}
    int mid=tree[k].l+tree[k].r>>1;
    if(l<=mid)update(k*2,l,r,t);
    if(r>mid)update(k*2+1,l,r,t);
}
ll ksm(int x)
{
    int y=mod-2;ll sum=1;
    while(y)
    {
        if(y&1)sum=(ll)sum*x%mod;
        x=(ll)x*x%mod;y>>=1;
    }
    return sum;
}
void solve(int k,int p)
{
    ll lans=ans;
    for(int i=0;isi[f2])
            {
                zh[p][++top[p]]=(xx){f2,f1,si[f2]};
                si[f1]+=si[f2];par[f2]=f1;
            }
            else
            {
                zh[p][++top[p]]=(xx){f1,f2,si[f1]};
                si[f2]+=si[f1];par[f1]=f2;
            }
        }
    }
    if(tree[k].l==tree[k].r)printf("%lld\n",ans);
    else solve(k*2,p+1),solve(k*2+1,p+1);
    for(int i=top[p];i>=1;--i)
    {
        si[zh[p][i].x]=zh[p][i].z;par[zh[p][i].x]=zh[p][i].x;
        si[zh[p][i].y]-=zh[p][i].z;
    } 
    ans=lans;top[p]=0;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d%d",&s[i].opt,&s[i].x,&s[i].y);
        if(s[i].x>s[i].y)swap(s[i].x,s[i].y);
        if(!dy[s[i].x][s[i].y])
            dy[s[i].x][s[i].y]=++cnt,prex[cnt]=s[i].x,prey[cnt]=s[i].y;
    }
    build(1,1,m);
    for(int i=1,u;i<=m;++i)
    {
        u=dy[s[i].x][s[i].y];
        if(s[i].opt==1)las[u]=i;
        else update(1,las[u],i-1,u),las[u]=0;
    }
    for(int i=1,u;i<=m;++i)
    {
        u=dy[s[i].x][s[i].y]; 
        if(las[u])update(1,las[u],m,u),las[u]=0;
    }
    for(int i=1;i<=n;++i)par[i]=i,si[i]=1,ny[i]=ksm(i);
    solve(1,1);
}

 

你可能感兴趣的:(3988: 地理课(geography))