【XSY2741】网格 分治 LCT 并查集
题目描述
有一个\(n\times m\)的网格,线框的交点可以扭动,边不可伸缩。网格中有一些格子里面放了'x'形的支架,这些格子不会变形,但可以整体转动。如果所有格子都不能变形,那么称这个网格稳固。
有\(q\)个操作,每次改变一个格子的状态,即有支架给为无支架,无支架改为有支架。
请你判断初始及每次操作后这个网格是否稳固。
比如说下面这个网格就不稳固。

\(n,m\leq 3000,q\leq 100000\)
题解
先看看怎么判断一个网格是否稳固。
先给整个网格的左边和上边加上一行一列,然后把第一行的最左边两个格子设为有支架的格子,其他的设为没支架的格子。
样例那个图就会变成这样

可以发现这样操作是不会改变整个图形的稳定性的。
设格子\((i,j)\)右下角的角度为\(a_{i,j}+90\)。
因为一个交点四个角的度数和为\(360\),所以可以列出以下方程:
90+a_{i-1,j-1}+180-90-a_{i-1,j}+180-90-a_{i,j-1}+90+a_{i,j}&=360\\
a_{i-1,j-1}+a_{i,j}-a_{i,j-1}-a_{i-1,j}&=0
\end{align}
\]
然后通过一些简单变换可以得到
\]
因为\(a_{0,0}=0\),所以方程简化为
\]
当\((i,j)\)有支架时\(a_{i,0}+a_{0,j}=a_{i,j}=0\),即\(a_{i,0}=-a_{0,j}\),那么我们就在图\(G\)的\(i\)和\(j+n\)两个点之间连一条边。
显然这个图是二分图。
因为边界上只有\(a_{0,1}=0\),所以一个点只有和\(n+1\)号点\((0,1)\)属于同一个联通块,这个点对应的角的角度才是确定的。
当\((i,j)\)无支架时\(a_{i.j}=a_{i,0}+a_{0,j}\)。如果\(a_{i,0}\)和\(a_{0,j}\)之间有一个没有确定,那么\(a_{i,j}\)也没有确定。
所以说,这个网格是稳定的\(\Longleftrightarrow\)图\(G\)只有一个联通块。
现在问题就变成了:有一个\(n+m\)个点的图,有\(nm\)条边,还有\(q\)个加边删边的操作。问操作前和每一次操作完后联通块个数是不是\(1\)。
用分治+并查集和LCT都可以做。
可以把一定存在的边先用路径压缩的并查集处理完。
分治+并查集:\(O(nm\alpha+q\log^2(n+m))\)
LCT:\(O(nm\alpha+q\log (n+m))\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<utility>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
vector<pii> a[400010];
int f[10010];
int r[10010];
int ans[100010];
int s1[10010];//x
int s2[10010];//f[x]
int s3[10010];//r[f[x]]
int top;
int n,m,q;
char s[10010];
int c[3010][3010];
int find(int x)
{
return f[x]==x?x:find(f[x]);
}
int find2(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
int num=0;
int merge(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return 0;
if(r[x]>r[y])
swap(x,y);
top++;
s1[top]=x;
s2[top]=y;
s3[top]=r[y];
if(r[x]==r[y])
r[y]++;
f[x]=y;
return 1;
}
int merge2(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return 0;
if(r[x]>r[y])
swap(x,y);
f[x]=y;
if(r[x]==r[y])
r[y]++;
return 1;
}
void back()
{
f[s1[top]]=s1[top];
r[s2[top]]=s3[top];
top--;
}
void add(int p,int l,int r,int x,int y,int L,int R)
{
if(l<=L&&r>=R)
{
a[p].push_back(pii(x,y));
return;
}
int mid=(L+R)>>1;
if(l<=mid)
add(p<<1,l,r,x,y,L,mid);
if(r>mid)
add((p<<1)|1,l,r,x,y,mid+1,R);
}
void solve(int l,int r,int p)
{
int now=top;
for(auto v:a[p])
if(merge(v.first,v.second))
num++;
if(l==r)
ans[l]=(num==n+m-1);
else
{
int mid=(l+r)>>1;
solve(l,mid,p<<1);
solve(mid+1,r,(p<<1)|1);
}
while(top>now)
{
back();
num--;
}
}
int main()
{
open("grid");
scanf("%d%d%d",&n,&m,&q);
memset(c,-1,sizeof c);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=m;j++)
if(s[j]=='x')
c[i][j]=0;
}
for(int i=1;i<=n+m;i++)
{
f[i]=i;
r[i]=1;
}
int x,y;
for(int i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
if(~c[x][y])
{
add(1,c[x][y],i-1,x,y+n,0,q);
c[x][y]=-1;
}
else
c[x][y]=i;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(~c[i][j])
{
if(c[i][j])
add(1,c[i][j],q,i,j+n,0,q);
else
if(merge2(i,j+n))
num++;
}
for(int i=1;i<=n+m;i++)
find2(i);
solve(0,q,1);
for(int i=0;i<=q;i++)
if(ans[i])
printf("S\n");
else
printf("U\n");
return 0;
}
【XSY2741】网格 分治 LCT 并查集的更多相关文章
- 【CF938G】Shortest Path Queries(线段树分治,并查集,线性基)
[CF938G]Shortest Path Queries(线段树分治,并查集,线性基) 题面 CF 洛谷 题解 吼题啊. 对于每个边,我们用一个\(map\)维护它出现的时间, 发现询问单点,边的出 ...
- 【BZOJ4025】二分图(线段树分治,并查集)
[BZOJ4025]二分图(线段树分治,并查集) 题面 BZOJ 题解 是一个二分图,等价于不存在奇环. 那么直接线段树分治,用并查集维护到达根节点的距离,只计算就好了. #include<io ...
- 【bzoj4998】星球联盟 LCT+并查集
题目描述 在遥远的S星系中一共有N个星球,编号为1…N.其中的一些星球决定组成联盟,以方便相互间的交流.但是,组成联盟的首要条件就是交通条件.初始时,在这N个星球间有M条太空隧道.每条太空隧道连接两个 ...
- 【bzoj2959】长跑 LCT+并查集
题目描述 某校开展了同学们喜闻乐见的阳光长跑活动.为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动.一时间操场上熙熙攘攘,摩肩接踵,盛况空前.为了 ...
- Dash Speed【好题,分治,并查集按秩合并】
Dash Speed Online Judge:NOIP2016十联测,Claris#2 T3 Label:好题,分治,并查集按秩合并,LCA 题目描述 比特山是比特镇的飙车圣地.在比特山上一共有 n ...
- 【BZOJ2049】 [Sdoi2008]Cave 洞穴勘测 LCT/并查集
两种方法: 1.LCT 第一次LCT,只有link-cut和询问,无限T,到COGS上找了数据,发现splay里的父亲特判出错了(MD纸张),A了,好奇的删了反转T了.... #include < ...
- 【BZOJ】2049: [Sdoi2008]Cave 洞穴勘测(lct/并查集)
http://www.lydsy.com/JudgeOnline/problem.php?id=2049 bzoj挂了..在wikioi提交,,1A-写lct的速度越来越快了-都不用debug-- 新 ...
- BZOJ_2049_[Sdoi_2008]_Cave_洞穴勘测_(LCT/并查集)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2049 给出一个森林,起始互不相连,现在有link和cut两种操作,问x,y是否在一棵树里. 分 ...
- 【BZOJ2959】长跑 (LCT+并查集)
Time Limit: 1000 ms Memory Limit: 256 MB Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能“为祖国健康工作五十年”,同学们纷纷离开寝室 ...
随机推荐
- xampp 使用过程中刚遇到的问题记录
开始使用XAMPP的时候,都是可以正常连接的,但是过一段时间后,在用它创建表或其他操作,会报错,提示如下错误 Access denied for user ''@'localhost' to data ...
- 网络拓扑自动发掘之三层设备惯用的SNMP OID的含义
原文地址:https://blog.csdn.net/maty_wang/article/details/81305070 1. ipNetToMediaIfIndex Name/OID: ipNet ...
- hdu 1730 Nim博弈
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1730 Nim博弈为:n堆石子,每个人可以在任意一堆中取任意数量的石子 n个数异或值为0就后手赢,否则先 ...
- Nginx Configuring HTTPS servers
Configuring HTTPS servershttp://nginx.org/en/docs/http/configuring_https_servers.html Configuring HT ...
- 实验楼----PHP代码审计(sha1、md5)
地址:http://www.shiyanbar.com/ctf/1787 题目:
- CentOS 7 安装配置带用户认证的squid代理服务器
这里只简述搭建一个带用户认证的普通代理 一.安装 安装过程十分简便,只需要安装一下squid,一条命令搞定 yum install squid rpm -qa | grep squid squid-- ...
- 四、Object.defineProperty总结
Object.defineProperty() 参考:https://segmentfault.com/a/1190000007434923 定义: 方法会直接在一个对象上定义一个新属性,或者修改一个 ...
- spring核心思想:IOC(控制反转)和DI(依赖注入)
Spring有三大核心思想,分别是控制反转(IOC,Inversion Of Controller),依赖注入(DI,Dependency Injection)和面向切面编程(AOP,Aspect O ...
- Tomcat 目录结构以及基本配置
1 Tomcat 目录层次结构 ① bin:存放启动和关闭tomcat 的脚本文件② conf: 存放配置文件 server.xml:该文件用于配置和server 相关的信息,比如tomcat 启动端 ...
- Oracle 序列(sequence)
序列(sequence) 是Oracle提供的用于生成一系列唯一数字的数据库对象.它会自动生成顺序递增或者递减的序列号,以实现自动提供唯一的主键值.序列可以在多用户并发环境中使用,并且可以为所有用户生 ...