【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 某校开展了同学们喜闻乐见的阳光长跑活动.为了能“为祖国健康工作五十年”,同学们纷纷离开寝室 ...
随机推荐
- POJ - 2528 区间离散化,线段树区间修改,区间询问
这个题非常有意思的地方是,我们发现区间[1,4]和[5,8]是紧挨着的,因为这个的数代表的是一段区间,原本我们对于普通的离散, a[1]=1,a[2]=5,a[3]=6,a[4]=8;数组下标就是重新 ...
- 通过Webstorm上传代码到Github、更新代码后同步到github及克隆github代码到本地的方法
导读: Github做为IT爱好者分享代码的一个知名的平台,广受大家喜欢,那么我们平时该怎么将自己写的代码上传到github上面保存并且提供给其他人参考? 我想方法不外乎如下几个: 1.直接在gith ...
- WinForm 进度条
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- PS调出清新淡雅外景女生背影照
首先,依然是前期事项. 这套图是八月份下午三点多在草地上拍的(好像标题的秋日欺骗了大众XD),阳光很烈,不过也因为这样,能拍出比较清新的蓝天.用的是腾龙70-200 2.8VC拍摄,长焦在拍这种空旷大 ...
- PS提亮户外儿童照
(@摄影师延延)作品 调整完的图. 原图. 再看原图.好吧,这张照片明显欠曝了,蘑菇酱的小脸黑黑的.但是构图啊蘑菇酱的神情啊都不错捏.好在蘑菇妈是用raw格式拍,即刻Lightroom调整无压力. 1 ...
- Linux之查看系统配置命令
1.查看CPU个数: [root@ifusion ~]# lscpu 2.查看CPU进程数.核数: [root@ifusion ~]# cat /proc/cpuinfo 3.查看内存总量: [roo ...
- CI框架在控制器中切换读写库和读写库
CodeIgniter框架版本:3.1.7 ,php版本:5.6.* ,mysql版本:5.6 在Ci框架中,可以在application/config/database.php中配置多个group, ...
- PHP 高并发秒杀解决方案
本文提供 PHP 高并发秒杀解决方案(附加三个案例说明(普通流程,使用文件锁,使用redis消息队列)) 1:(正常流程,不做任何高并发处理),代码如下: <?php $_mysqli = ne ...
- Vue+iview实现添加删除类
<style> .tab-warp{ border-bottom: solid 1px #e0e0e0; overflow: hidden; margin-top: 30px; posit ...
- easyUI定区关联快递员js代码
easyUI定区关联快递员js代码: <script type="text/javascript"> $.fn.serializeJson=function(){ va ...