3988: 地理课(geography)

题目描述

 

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

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

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

 

 

输入

 

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

 

 

输出

 

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

 

 

样例输入

<span style="color:#333333"><span style="color:#333333">样例输入#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
</span></span>

样例输出

<span style="color:#333333"><span style="color:#333333">样例输出#1
2
3
3
6
5
6
样例输出#2
见example\geography\geography2.out
样例输出#3
见example\geography\geography3.out
</span></span>

提示

 

 

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

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<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#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;
    vector<int>v;
}tree[400005];
map<int,int>dy[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;i<tree[k].v.size();++i)
    {
        int x=prex[tree[k].v[i]],y=prey[tree[k].v[i]];
        int f1=find(x),f2=find(y);
        if(f1!=f2)
        {
            ans=(ll)ans*ny[si[f1]]%mod*ny[si[f2]]%mod*(si[f1]+si[f2])%mod;
            if(si[f1]>si[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);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值