bzoj4153 [Ipsc2015]Familiar Couples
2016-03-29 19:15
260 查看
Description
有n对夫妇,一开始夫妇之间互不认识,若两男或两女成为朋友,称他们为"熟人","熟人"关系具有传递性,即若a熟b且b熟c则a熟c.若两组夫妇的丈夫互相为熟人且妻子也相互为熟人则称他们为"熟悉的一对",现在给出q个事件,每个事件会使得两男或两女成为朋友,并在每次事件之后计算"熟悉的一对"的个数.Input
第一行一个数T表示数据组数接下来n,q表示对数和事件数
接下来q行,每行t,a,b,若t=1,表示男a和男b成为朋友,t=2,表示女a和女b成为朋友
Output
设当前是第i个操作,y_i为本次事件之后的答案,令z_i=i*y_i,请输出z_1+z_2+...+z_q模10^9+7题意简化为维护两个图,支持在一个图中连边和询问有多少点对在两个图中都连通
用两个并查集分别维护两个图中的连通性,用一个hashmap维护一个n*n的二维数组,f[x][y]表示在并查集1中属于集合x,在并查集2中属于集合y的点的个数
每次在一个图中连边时,若两侧连通则忽略,不联通则遍历小的一个联通块,通过计算在另一个图中跨过两个联通块的联通块更新答案
均摊时间复杂度O(Tnlogn)
#include<cstdio>#include<vector> const int P=1e9+7,N=1e6+5; inline int read(){ int x=0,c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x; } inline void exch(int&a,int&b){int c=a;a=b;b=c;}namespace Map{ const int mx=2939999; unsigned int nw=0; unsigned int xs[mx],ys[mx],zs[mx],ds[mx]; inline void clear(){ nw++; } inline int get(unsigned int x,unsigned int y,int inc){ unsigned int w=(x*17+y*53+3)%mx; while(ds[w]==nw){ if(xs[w]==x&&ys[w]==y){ int v=zs[w]; zs[w]+=inc; return v; } w+=1237; if(w>=mx)w-=mx; } ds[w]=nw; xs[w]=x;ys[w]=y;zs[w]=inc; return 0; } } int T,n,m,now=1,Ans,ans; int h1 ,h2 ,f1 ,f2 ,sz1 ,sz2 ,nx1 ,nx2 ; int t ,d ; std::vector<int>v1 ,v2 ; int main(){ T=read(); while(T--){ n=read();m=read(); Ans=ans=0; Map::clear(); for(int i=1;i<=n;i++){ Map::get(i,i,1); f1[i]=f2[i]=i; v1[i].clear();v2[i].clear(); v1[i].push_back(i); v2[i].push_back(i); } for(int i=1,op,a,b;i<=m;++i){ op=read();a=read();b=read(); ++now; if(op==1){ if(f1[a]!=f1[b]){ if(v1[f1[a]].size()>v1[f1[b]].size())exch(a,b); std::vector<int>&vc=v1[f1[a]]; for(int x=0;x<vc.size();x++){ int p=vc[x]; int f=f2[p]; if(d[f]!=now)d[f]=now,ans=(ans+Map::get(f1[p],f,-1)*1ll*Map::get(f1[b],f,1)%P)%P; else Map::get(f1[p],f,-1),Map::get(f1[b],f,1); f1[p]=f1[b]; v1[f1[b]].push_back(p); } vc.clear(); } }else{ if(f2[a]!=f2[b]){ if(v2[f2[a]].size()>v2[f2[b]].size())exch(a,b); std::vector<int>&vc=v2[f2[a]]; for(int x=0;x<vc.size();x++){ int p=vc[x]; int f=f1[p]; if(d[f]!=now)d[f]=now,ans=(ans+Map::get(f,f2[p],-1)*1ll*Map::get(f,f2[b],1)%P)%P; else Map::get(f,f2[p],-1),Map::get(f,f2[b],1); f2[p]=f2[b]; v2[f2[b]].push_back(p); } vc.clear(); } } Ans=(Ans+ans*1ll*i%P)%P; } printf("%d\n",Ans); } return 0; }
相关文章推荐
- 第五周项目1 三角形类
- Python获取豆瓣新书列表
- 大数相乘与大数相加
- 1010 - Knights in Chessboard(找规律)
- 【Android】通用系列 —— 对话框
- 加载更多
- Tomcat配置Https环境
- 比较好用的办公软件
- 计算机程序的思维逻辑 (1)
- 在linux上配置unixODBC和FreeTDS访问MS SQL Server.
- mac ssh常见问题
- iOS quartzCore第一章——CADisplayLink详解 及与NSTimer的区别(类型为翻译,主要是自己好找)
- xcode常见报错调试
- 递归求阶乘
- 递归求阶乘
- 递归求阶乘
- 递归求阶乘
- 递归求阶乘
- 【小白学数据库】SQL批量模糊查询
- Go语言学习一 :基础语句