UVA1455 【Kingdom】
分析
直线都是\(y=\overline{a.5}\)这种形式,而只查询州和城市的个数,所以很容易想到对\(y\)轴做投影,然后转化为区间修改(加减)和单点查询,可以用线段树维护。至于每个州只会合并不会分裂,大小肯定是只增不减的,所以用并查集维护很方便。
算法流程
线段树维护区间的州和城市的个数,以及它们的标记。
并查集要维护它的大小,纵坐标范围。
- road A B:如果A、B本身同属一个州就不管,因为肯定有覆盖A、B纵坐标的路连接它们两个。否则先撤销A、B所属州对线段树的贡献,然后合并两个州,最后把并集的贡献加到线段树上。
- line C:我规定线段树上\([i,i]\)节点管辖\(y\)轴上\([i,i-1]\)区间,也就是\(y=\overline{(i-1).5}\)这条直线。那么此操作相当于查询\([C+0.5,C+0.5]\)这个节点。
时间复杂度
建树复杂度\(O(n\log n)\)。单次操作无论是road A B还是line C都是\(O(\log n)\)的,而有\(m\)次操作,所以总时间复杂度为\(O(n\log n+m \log n)\)。
代码
#include<iostream>
#include<cstdio>
#define reg register
#pragma GCC optimize(3)
template<typename T>T read(T&x)
{
T data=0;
int w=1;
char ch=getchar();
while(ch!='-'&&!isdigit(ch))
ch=getchar();
if(ch=='-')
w=-1,ch=getchar();
while(isdigit(ch))
data=data*10+ch-'0',ch=getchar();
return x=data*w;
}
using namespace std;
const int MAXN=1e5+1,MAXY=1e6+1;
struct SegTree // leaf node i controls y=i->(i-1)
{
int sums,sumc;
int adds,addc;
}ST[MAXY<<2];
#define root ST[o]
#define lson ST[o<<1]
#define rson ST[o<<1|1]
inline void pushup(int o)
{
root.sums=lson.sums+rson.sums;
root.sumc=lson.sumc+rson.sumc;
}
void build(int o,int l,int r)
{
if(l==r)
{
root.sums=root.sumc=0;
root.adds=root.addc=0;
return;
}
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
pushup(o);
root.adds=root.addc=0;
}
inline void pushdown(int o,int l,int r)
{
int mid=(l+r)>>1;
if(root.adds)
{
lson.sums+=root.adds*(mid-l+1),
lson.adds+=root.adds;
rson.sums+=root.adds*(r-mid),
rson.adds+=root.adds;
root.adds=0;
}
if(root.addc)
{
lson.sumc+=root.addc*(mid-l+1),
lson.addc+=root.addc;
rson.sumc+=root.addc*(r-mid),
rson.addc+=root.addc;
root.addc=0;
}
}
void addrg(int o,int l,int r,int ql,int qr,int state,int city)
{
if(ql<=l&&r<=qr)
{
root.sums+=state*(r-l+1),
root.adds+=state;
root.sumc+=city*(r-l+1),
root.addc+=city;
return;
}
pushdown(o,l,r);
int mid=(l+r)>>1;
if(ql<=mid)
addrg(o<<1,l,mid,ql,qr,state,city);
if(qr>=mid+1)
addrg(o<<1|1,mid+1,r,ql,qr,state,city);
pushup(o);
}
SegTree querypt(int o,int l,int r,int q)
{
if(l==r)
return root;
pushdown(o,l,r);
int mid=(l+r)>>1;
if(q<=mid)
return querypt(o<<1,l,mid,q);
else if(q>=mid+1)
return querypt(o<<1|1,mid+1,r,q);
}
struct Point
{
int x,y;
}P[MAXN];
typedef Point Range;
int fa[MAXN],sz[MAXN];
Range rg[MAXN]; // y=x->y(x<y)
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline void unite(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx==fy) return;
if(rg[fx].x+1<=rg[fx].y)
{
addrg(1,1,1e6,rg[fx].x+1,rg[fx].y,-1,-sz[fx]);
}
if(rg[fy].x+1<=rg[fy].y)
{
addrg(1,1,1e6,rg[fy].x+1,rg[fy].y,-1,-sz[fy]);
}
sz[fy]+=sz[fx],sz[fx]=0;
fa[fx]=fy;
rg[fy].x=min(rg[fy].x,rg[fx].x),rg[fy].y=max(rg[fy].y,rg[fx].y);
if(rg[fy].x+1<=rg[fy].y)
{
addrg(1,1,1e6,rg[fy].x+1,rg[fy].y,1,sz[fy]);
}// ->segtree bomb
}
int main()
{
int T;
read(T);
while(T--)
{
build(1,1,1e6);
int n;
read(n);
for(reg int i=0;i<n;++i)
{
read(P[i].x);read(P[i].y);
fa[i]=i;
sz[i]=1;
rg[i].x=rg[i].y=P[i].y;
}
int m;
read(m);
for(reg int i=1;i<=m;++i)
{
char opt[10];
scanf("%s",opt);
if(opt[0]=='r')
{
int A,B;
read(A);read(B);
unite(A,B);
}
else if(opt[0]=='l')
{
double C;
scanf("%lf",&C);
C+=0.5;
SegTree t=querypt(1,1,1e6,C);
printf("%d %d\n",t.sums,t.sumc);
}
}
}
}
Hint
线段树大小还可以继续优化。
UVA1455 【Kingdom】的更多相关文章
- 【CF613D】Kingdom and its Cities 虚树+树形DP
[CF613D]Kingdom and its Cities 题意:给你一棵树,每次询问给出k个关键点,问做多干掉多少个非关键点才能使得所有关键点两两不连通. $n,\sum k\le 10^5$ 题 ...
- 【CF687D】Dividing Kingdom II 线段树+并查集
[CF687D]Dividing Kingdom II 题意:给你一张n个点m条边的无向图,边有边权$w_i$.有q个询问,每次给出l r,问你:如果只保留编号在[l,r]中的边,你需要将所有点分成两 ...
- 【CF613D】Kingdom and its Cities
[CF613D]Kingdom and its Cities 题面 洛谷 题解 看到关键点当然是建虚树啦. 设\(f[x]\)表示以\(x\)为根的子树的答案,\(g[x]\)表示以\(x\)为根的子 ...
- 【CF613D】Kingdom and its Cities(虚树,动态规划)
[CF613D]Kingdom and its Cities(虚树,动态规划) 题面 洛谷 CF 翻译洛谷上有啦 题解 每次构建虚树,首先特判无解,也就是关键点中存在父子关系. 考虑\(dp\),设\ ...
- SCI&EI 英文PAPER投稿经验【转】
英文投稿的一点经验[转载] From: http://chl033.woku.com/article/2893317.html 1. 首先一定要注意杂志的发表范围, 超出范围的千万别投,要不就是浪费时 ...
- 【LA3523】 Knights of the Round Table (点双连通分量+染色问题?)
Being a knight is a very attractive career: searching for the Holy Grail, saving damsels in distress ...
- 我的Android进阶之旅------>Android【设置】-【语言和输入法】-【语言】列表中找到相应语言所对应的列表项
今天接到一个波兰的客户说有个APP在英文状态下一切运行正常,但是当系统语言切换到波兰语言的时候,程序奔溃了.所以首先我得把系统的语言切换到波兰语,问题是哪个是波兰语呢? 我还真的不认识哪个列表项代表着 ...
- 【BZOJ3864】Hero meet devil DP套DP
[BZOJ3864]Hero meet devil Description There is an old country and the king fell in love with a devil ...
- 【转载】How to develop your own Boot Loader【怎么样开发自己的bootloader】
How to develop your own Boot Loader 怎么样开发自己的bootloader Table of content[目录] 1. Who may be interested ...
随机推荐
- U帮忙U盘启动盘制作
第一步:制作U盘启动盘前的软.硬件准备 1.准备一个U盘或内存卡(尽量使用2G以上的) 2.进入 U帮忙官网 下载最新版U盘启动盘制作工具! 3.搜索并下载ghost版系统文件存放到电脑中. 第二步: ...
- nginx入门示例(二)
nginx使用域名访问 (Tip) nginx目录解析 conf/nginx.conf #主要的配置文件目录 html #nginx的默认发布目录,部署完后 网站会在这个目录 ...
- 戴尔poweredge r730服务器配置以及系统安装
第一次给服务器安装的是ubantu系统: 首先我们开机进入小型BIOS设置一下RAID,或者进入服务器管理系统,在系统的BIOS中进行RAID设置: 开机后当看到出现< Ctrl > &l ...
- HTML语义化简介思维导图
- IntelliJ IDEA导入Javax包(servlet-api.jar)
在初次使用 IntelliJ IDEA 中,当你使用javax.servlet包下的类时(例:javax.servlet.http.HttpServlet), 在你会发现在IntelliJ IDEA里 ...
- TransactionScop事务机制的使用
如果在C#中使用TransactionScope类(分布式事务),则须注意如下事项:1.在项目中引用using System.Transactions命名空间(先要在添加net组件的引用); 2.具体 ...
- Oracle 12c 容器讲解
Oracle 12c一个重要新特性是插接式数据库. 插接式数据库由一个使用 CDB(Container Database)选项创建的容器数据库和一个或多个 PDB(Pluggable Database ...
- Day17作业及默写
正则表达式练习 1.匹配一篇英文文章的标题 类似 The Voice Of China ([A-Z][a-z]*)( [A-Z][a-z]*)* 2.匹配一个网址 https://www.baidu. ...
- [Mac]ssh免密登陆配置
在已经有公钥和私钥的情况下,只需要以下三步即可实现免密登陆: 1.将已有rsa公钥和私钥拷贝到~/.ssh目录下. 2.编辑配置文件:vim ~/.ssh/config,内容如下: Host xxx ...
- 使用Chrome调试工具抢阿里云免费套餐
活动地址如下: https://free.aliyun.com/ntms/free/experience/getTrial.html 首先打开地址,需要登录,登陆后看到如下页面: 选择个人免费套餐,这 ...