博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UVALive 4730 - Kingdom(并查集+线段树)
阅读量:5222 次
发布时间:2019-06-14

本文共 3291 字,大约阅读时间需要 10 分钟。

题目链接

【题意】

平面上有n个城市,初始时城市之间没有任何双向道路相连,你的任务是依次执行以下指令
road A B 在城市A,B之间建立一条双向道路,保证这条道路不和其它道路在非端点处相交
line C 询问一条y=C的水平线和多少个州相交,以及这些州一共包含多少个城市,在任意时刻,每一组连通的城市形成一个州,保证C的小数部分为0.5

【输入格式】

多组输入,第一行为数据组数T. 每组数据第一行为一个整数n(1<=n<=1e5)代表城市数量,以下n行每行两个整数x,y(0 <= x,y <= 1e6)城市编号为0~n-1. 下一行为指令总数m(1<=m<=200000)以下m行每行一条指令,其中A,B为不同的整数且0<=A< B< N, C是小数部分保证为0.5的实数,且0 < C <1000000. 不会有两条道路连接相同的城市,每组数据至少有一条line指令

【输出格式】

对于每条line指令,输出y=C穿过的州的数目以及这些州包含的城市总数

【思路】

把每个城市抽象成点,题目中的州其实就是一个连通块,我们可以用并查集来维护一个连通块的信息,我们需要维护一个连通块中城市的数目,还有就是纵坐标的最大值和最小值以便进行合并。而合并操作又可以借助于线段树来完成,首先可以将坐标统一乘以2使得坐标值均为整数,之后对y轴上的每一个点抽象成线段树的一个叶子结点,线段树叶子结点维护2个信息,即这一点的坐标穿过的州的数量和对应城市的数量(非叶结点这两个值是无意义的)合并两个连通块的过程其实是把原来的两个连通块删掉,加入合并后的新连通块。比如在合并两个连通块A和B的时候,首先把A,B原来各自的区间对应的州的数量减1,城市数量减去自己的城市数量,然后在合并后的新的区间中使得州的数量加1,城市数量加上A,B城市的总数量.可以用lazy标记维护区间和来实现区间更新,最后单点查询即可因为只有叶子结点的信息有意义.

#include
#define node tree[id]#define lson tree[id<<1]#define rson tree[id<<1|1]using namespace std;const int maxn=1000005;const int maxm=2000050;struct Tree{ int left,right; int num,city; int lazy1,lazy2;};int n,m;int par[maxn];int maxy[maxn],miny[maxn],cnt[maxn];int x[maxn],y[maxn];Tree tree[maxm<<2];void init(){ for(int i=0;i<=n;++i) par[i]=i; memset(maxy,0,sizeof(maxy)); memset(miny,0,sizeof(miny)); memset(cnt,0,sizeof(cnt));}int find(int x){ return x==par[x]?x:par[x]=find(par[x]); }void pushup(int id){ node.num=lson.num+rson.num; node.city=lson.city+rson.city;}void pushdown(int id){ if(node.lazy1 && node.left!=node.right){ lson.lazy1+=node.lazy1; lson.num+=(lson.right-lson.left+1)*node.lazy1; rson.lazy1+=node.lazy1; rson.num+=(rson.right-rson.left+1)*node.lazy1; node.lazy1=0; } if(node.lazy2 && node.left!=node.right){ lson.lazy2+=node.lazy2; lson.city+=(lson.right-lson.left+1)*node.lazy2; rson.lazy2+=node.lazy2; rson.city+=(rson.right-rson.left+1)*node.lazy2; node.lazy2=0; }}void build(int id,int le,int ri){ node.left=le; node.right=ri; node.num=node.city=0; node.lazy1=node.lazy2=0; if(le==ri) return; int mid=(le+ri)>>1; build(id<<1,le,mid); build(id<<1|1,mid+1,ri);}void update(int id,int le,int ri,int a,int b){ if(node.left==le && node.right==ri){ node.lazy1+=a; node.num+=(node.right-node.left+1)*a; node.lazy2+=b; node.city+=(node.right-node.left+1)*b; return; } pushdown(id); int mid=(node.left+node.right)>>1; if(ri<=mid) update(id<<1,le,ri,a,b); else if(le>mid) update(id<<1|1,le,ri,a,b); else{ update(id<<1,le,mid,a,b); update(id<<1|1,mid+1,ri,a,b); } pushup(id);}int query(int id,int pos){ if(node.left==node.right) return id; pushdown(id); int mid=(node.left+node.right)>>1; if(pos<=mid) return query(id<<1,pos); else return query(id<<1|1,pos);}int main(){ //freopen("in.txt","r",stdin); //freopen("out2.txt","w",stdout); int T; scanf("%d",&T); while(T--){ scanf("%d",&n); init(); int maxr=0; for(int i=0;i
maxr) puts("0 0"); else{ int id=query(1,p); printf("%d %d\n",node.num,node.city); } } } } return 0;}

转载于:https://www.cnblogs.com/wafish/p/10465262.html

你可能感兴趣的文章
B2321 [BeiJing2011集训]星器 数学&&物理
查看>>
201571030319 四则运算
查看>>
RestTemplate 调用本地服务 connection refused
查看>>
.NET方向高级开发人员面试时应该事先考虑的问题
查看>>
台达PLC modbus 不支持04功能码
查看>>
python学习笔记--装饰器
查看>>
发布一个JavaScript工具类库jutil,欢迎使用,欢迎补充,欢迎挑错!
查看>>
discuz 常用脚本格式化数据
查看>>
MS CRM 2011 创建基于Fetch的报表 -- 进阶版
查看>>
洛谷P2777
查看>>
PHPStorm2017设置字体与设置浏览器访问
查看>>
SQL查询总结 - wanglei
查看>>
安装cocoa pods时出现Operation not permitted - /usr/bin/xcodeproj的问题
查看>>
makefile中使用变量
查看>>
GIT笔记:将项目发布到码云
查看>>
JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别
查看>>
JavaScript 鸭子模型
查看>>
PHP典型功能与Laravel5框架开发学习笔记
查看>>
SQL Server 如何查询表定义的列和索引信息
查看>>
GCD 之线程死锁
查看>>