UVALive
来源:互联网 发布:web of science数据库 编辑:程序博客网 时间:2024/06/03 13:55
题目链接:http://https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2731;
题目大意:在一个平面上有n个城市,初始时的城市之间没有任何双向道路相连。你的任务是依次执行以下两种指令:
1、road A B:在城市A和城市B之间连接一条双向道路,保证这条道路不和其他道路在这非端点处相交;
2、 line C : 询问一条y=C的水平线和多少个州相交,以及这些州一共包括多少座城市。在任意时刻,每一组连通的城市形成一个州。(C的小数部分保证为0.5)。
题目思路:因为要求联通块的数量以及联通块中点的数量,自然就想到了用并查集来维护。对于求解方法可以建立两棵以y轴的坐标为下标的线段树,一棵维护联通块数量,一棵维护点的数量。在用并查集维护的点同时可以维护一下当前联通块的上届up和下届down,则在线段树的[down,up]区间内所有的联通块数量就等于所有上届和下届在[down,up]区间之内的联通块的数量和,城市数量也是如此。最后再用一个查询,查出C所对应的线段树的下标即可找到答案。具体实现看代码。
AC代码如下:
#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define fuck(x) cout<<'['<<x<<']'<<endl#define FIN freopen("in.txt","r",stdin)#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define mem(a,b) memset(a,b,sizeof(a))using namespace std;typedef long long LL;typedef pair<int, int>pii;const int MX = 1e6 + 7;const int maxn = 1e5 + 7;int T,n,m;int sum1[MX<<2],sum2[MX<<2],add1[MX<<2],add2[MX<<2];int P[maxn],up[maxn],down[maxn],num[maxn];//up[i]表示第i个联通块的上界,down[i]表示第i个联通块的下界,num[i]表示第i个联通块中包含的城市的数量;int found(int x){ return P[x] == x ? x : (P[x] = found(P[x]));}void push_up(int rt){ sum1[rt] = sum1[rt<<1] + sum1[rt<<1|1];//州的数量; sum2[rt] = sum2[rt<<1] + sum2[rt<<1|1];//城市的数量;}void push_down(int rt){ if(add1[rt]){ add1[rt<<1] += add1[rt]; add1[rt<<1|1] += add1[rt]; sum1[rt<<1] += add1[rt]; sum1[rt<<1|1] += add1[rt]; add1[rt] = 0; } if(add2[rt]){ add2[rt<<1] += add2[rt]; add2[rt<<1|1] += add2[rt]; sum2[rt<<1] += add2[rt]; sum2[rt<<1|1] += add2[rt]; add2[rt] = 0; }}void update(int op,int L,int R,int d,int l,int r,int rt){ if(L > R) return; if(L <= l && r <= R){ if(!op){ //更新区间中州的数量; add1[rt] += d; sum1[rt] += d; } else{ //更新区间中城市的数量; add2[rt] += d; sum2[rt] += d; } return; } int m = (l + r) >> 1; push_down(rt); if(L <= m) update(op,L,R,d,lson); if(R > m) update(op,L,R,d,rson); push_up(rt);}int query(int p,int l,int r,int rt){ if(l == r) return rt; push_down(rt); int m = (l + r) >> 1; if(p <= m) return query(p,lson); else return query(p,rson); push_up(rt);}void init(){ mem(sum1,0);mem(sum2,0); mem(add1,0);mem(add2,0); for(int i = 0;i <= n;i++) P[i] = i;}void Union(int u,int v,int Max){ int uu = found(u); int vv = found(v); if(uu != vv){ if(up[uu] > up[vv]) swap(uu,vv);//保证u所在的联通块的上界小于v所在的联通块的上界以便后面的比较; if(down[vv] > up[uu]){//当两个联通块无交集的情况; update(0,up[uu]+1,down[vv],1,1,Max,1); //更新u所在的联通块的上界到v所在联通块的下界之间的区间联通块的数量; update(1,up[uu]+1,down[vv],num[uu]+num[vv],1,Max,1); //更新u所在的联通块的上界到v所在联通块的下界之间的区间城市的数量; update(1,down[uu]+1,up[uu],num[vv],1,Max,1); //更新u所在的联通块所在的区间的城市的数量; update(1,down[vv]+1,up[vv],num[uu],1,Max,1); //更新v所在的联通块所在的区间的城市的数量; } else if(down[uu] > down[vv]){//u所在的联通块完全在v所在的联通块的区间内; update(0,down[uu]+1,up[uu],-1,1,Max,1); //联通后,u所在的区间的联通块的数量-1; update(1,down[vv]+1,down[uu],num[uu],1,Max,1); //更新v所在的联通块的下界到u所在联通块的下界之间的区间城市的数量; update(1,up[uu]+1,up[vv],num[uu],1,Max,1); //更新u所在的联通块的上界到v所在联通块的上界之间的区间城市的数量; } else{//u所在的联通块一部分在v的联通块的区间内; update(0,down[vv]+1,up[uu],-1,1,Max,1); //联通后,v所在的联通块下界到u所在的联通块的上界的区间内的城市的数量-1; update(1,down[uu]+1,down[vv],num[vv],1,Max,1); //更新u所在的联通块的下界到v所在联通块的下界之间的区间城市的数量; update(1,up[uu]+1,up[vv],num[uu],1,Max,1); //更新u所在的联通块的上界到v所在联通块的上界之间的区间城市的数量; } P[uu] = vv;//更新联通块; num[vv] += num[uu];//更新联通块内点的数量 down[vv] = min(down[uu],down[vv]);//更新联通块的下界; up[vv] = max(up[uu],up[vv]);//更新联通块的上界; }}int main() { //FIN; scanf("%d",&T); while(T--){ scanf("%d",&n); init(); int Max = 0; for(int i = 0;i < n;i++){ int x,y; scanf("%d%d",&x,&y); up[i] = down[i] = y; num[i] = 1; Max = max(Max,y); } Max++; scanf("%d",&m); while(m--){ char op[10]; scanf("%s",op); if(op[0] == 'r'){ int u,v; scanf("%d%d",&u,&v); Union(u,v,Max); } else{ double line; scanf("%lf",&line); int p = query((int)(line+1),1,Max,1);//查询C所在的坐标的线段树下标; printf("%d %d\n",sum1[p],sum2[p]); } } } return 0;}
阅读全文
0 0
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- string转换为LPCWSTR
- 中点bresenham算法画线
- Lesson 3 上机练习题——继承
- [HNOI2004]打鼹鼠
- opencv归一化函数normalize详解
- UVALive
- 关于html,互相学习
- 深度学习,机器学习部分基本概念
- 深入理解java中的final关键字
- 【C/C++】列出连通集
- ActiveMQ 连接工厂
- openjudge noi 9278 旅行
- 第五周实践项目一__建立顺序栈算法库
- ACM工作室的日常记录-第二次内部测试