洛谷P3295 萌萌哒 并查集 + ST表
又切一道紫题!!!
成功的(看了一吨题解之后),我A掉了第二道紫题。
好,我们仔细观察,发现这是一个排列组合问题。
有些限定条件,要相等的地方,我们就用并查集并起来。最后一查有多少个并查集,就有多少个位置可供自由选择。
所以答案就是10^(并查集数),去除前导0:*(9/10)
好,这样我们得到了一个O(mn)算法。
然后我们考虑优化:每个区间可能被合并多次。所以我们有两种选择:线段树/ST表。
考虑到这是ST表例题(???????),我们就来个ST表与并查集联动求解...
我们的ufs[i][j]代表在[i][2^j]这个区间内的情况。
然后每次合并的时候都往下合并两个j-1(也可以最后再一起下传标记)
实质上是开了logn个并查集,因为我发现find和merge都不跨层。
题外话:与RE战斗的艰辛历程
交了11次RE,实在是让人感受绝望啊。
两种方法全都RE,所幸刚才我写的时候都查出来错了。
那么先来看看第一种方法:
每次都跟线段树一样恰好标记完最少的节点,最后所有标记一起下传。
#include <cstdio>
using namespace std;
const int N = ;
const int mo = ; int ufs[N][],n,m;
int find(int x,int j)
{
if(ufs[x][j]!=x) ufs[x][j]=find(ufs[x][j],j);
return ufs[x][j];
}
void merge(int x,int y,int j)
{
ufs[find(x,j)][j]=find(y,j);///->!!这里调了一个错,之前是ufs[x][j]=......
return;
} int main()
{
scanf("%d%d",&n,&m);
for(int j=;j<=;j++)
{
for(int i=;i<=n;i++) ufs[i][j]=i;///->!
}
int a,b,c,d;
int md=;
while((<<md)<=n) md++;
md--;
for(int i=;i<=m;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
for(int j=md;j>=;j--)
{
if(a+(<<j)-<=b) merge(a,c,j),a+=(<<j),c+=(<<j);
}
}
///
for(int j=md;j>=;j--)///这里,RE的罪魁祸首!我之前写的0,结果传进去个j=-1直接挂
{
for(int i=;i+(<<j)-<=n;i++)
{
merge(i,find(i,j),j-);
merge(i+(<<(j-)),find(i,j)+(<<(j-)),j-);
}
}
///
long long ans=;
bool q=false;
for(int i=;i<=n;i++)
{
if(find(i,)==i)
{
if(q) ans=(ans*)%mo;
q=;
}
}
//for(int i=1;i<=n;i++) printf("%d ",find(i,0));
printf("%lld",ans);
return ;
}
AC代码,跑的比下面快一些
第二种思路:
每次都传到底。如果已经在一起就不往下推了。
#include <cstdio>
using namespace std;
const int N = ;
const int mo = ; int ufs[N][],n,m;
int ffind(int x,int j)
{
//if(ufs[x][j]!=x) ufs[x][j]=find(ufs[x][j],j);
//return ufs[x][j];
if(j<) return ;
int ans=x,k;
while(ufs[ans][j]!=ans) ans=ufs[ans][j];
while(ufs[x][j]!=x)
{
k=ufs[x][j];
ufs[x][j]=ans;
x=k;
}
return ans;
}
void mmerge(int x,int y,int j)
{
if(j<) return;///这里控制情况,AC
if(ffind(x,j)==ffind(y,j)) return;
ufs[ffind(x,j)][j]=ffind(y,j);///->!!
mmerge(x,y,j-),mmerge(x+(<<(j-)),y+(<<(j-)),j-);///这里RE!会传入j=-1
return;
} int main()
{
scanf("%d%d",&n,&m);
for(int j=;j<=;j++)
{
for(int i=;i<=n;i++) ufs[i][j]=i;///->!
}
int a,b,c,d;
int md=;
while((<<md)<=n) md++;
md--;
for(int i=;i<=m;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
for(int j=md;j>=;j--)
{
if(a+(<<j)-<=b) mmerge(a,c,j),a+=(<<j),c+=(<<j);
}
}
/** */
long long ans=;
bool q=false;
for(int i=;i<=n;i++)
{
if(ffind(i,)==i)
{
if(q) ans=(ans*)%mo;
q=;
}
}
//for(int i=1;i<=n;i++) printf("%d ",find(i,0));
printf("%lld",ans);
return ;
}
AC代码
结论:函数里最好写上特判违法情况,保险。
洛谷P3295 萌萌哒 并查集 + ST表的更多相关文章
- bzoj 4569 [Scoi2016]萌萌哒 并查集 + ST表
题目链接 Description 一个长度为\(n\)的大数,用\(S_1S_2S_3...S_n\)表示,其中\(S_i\)表示数的第\(i\)位,\(S_1\)是数的最高位,告诉你一些限制条件,每 ...
- luogu3295 萌萌哒 (并查集+ST表)
如果给相同的位置连边,最后联通块数是n,最后答案就是$9*10^{n-1}$ 但直接连边是$O(n^2)$的 所以事先处理出一个ST表,每次O(1)地给那个ST表连边 最后再一点一点下放,就是把在这层 ...
- 【洛谷3865】 【模板】ST表(猫树)
传送门 洛谷 Solution 实测跑的比ST表快!!! 这个东西也是\(O(1)\)的,不会可以看我上一篇Blog 代码实现 代码戳这里
- 洛谷P3295 萌萌哒 [SCOI2016] 倍增+并查集
正解:倍增+并查集 解题报告: 传送门! 首先不难想到暴力?就考虑把区间相等转化成对应点对相等,然后直接对应点连边,最后求有几个连通块就好辣 然后看下复杂度,修改是O(n2)查询是O(n),就比较容易 ...
- 洛谷P4092树——并查集
题目:https://www.luogu.org/problemnew/show/P4092 利用并查集,倒序离线,那么从倒序来看被撤销标记的点就再也不会被标记,所以用并查集跳过: 莫名其妙的WA,调 ...
- 洛谷P2391 白雪皑皑(并查集)
题目背景 “柴门闻犬吠,风雪夜归人”,冬天,不期而至.千里冰封,万里雪飘.空中刮起了鸭毛大雪.雪花纷纷,降落人间. 美能量星球(pty 在 spore 上的一个殖民地)上的人们被这美景所震撼.但是 p ...
- 洛谷P3958 奶酪 并查集
两个空洞可互达当且仅当两个空洞相切,即球心距离小于等于球的直径. 一一枚举两个可互达的空洞,并用并查集连起来即可. Code: #include<cstdio> #include<c ...
- 洛谷 P3958 奶酪 并查集
目录 题面 题目链接 题面 题目描述 输入输出格式 输入格式 输出格式: 输入输出样例 输入样例 输出样例 说明 思路 AC代码 总结 题面 题目链接 P3958 奶酪 题面 题目描述 现有一块大奶酪 ...
- 洛谷 P2391.白雪皑皑 (并查集,思维)
题意:有\(n\)个点,对这些点进行\(m\)次染色,第\(i\)次染色会把区间\((i*p+q)\ mod\ N+1\)和\((i*q+p)\ mod\ N+1\)之间的点染成颜色\(i\),问最后 ...
随机推荐
- 在Ubuntu18.04下将应用程序添加到启动器
# 在启动器里面给应用程序添加一个快捷方式 在linux(ubuntu)平台下,很多小伙伴发现,自己去官网下载解压的软件不能自动添加到启动器,每次启动的时候需要再次进入软件目录输入命令,非常不方便.本 ...
- Redis+Keepalived高可用环境部署记录
Keepalived 实现VRRP(虚拟路由冗余)协议,从路由级别实现VIP切换,可以完全避免类似heartbeat脑裂问题,可以很好的实现主从.主备.互备方案,尤其是无状态业务,有状态业务就需要额外 ...
- Swarm基于多主机容器网络 - overlay networks 梳理
前面介绍了Docker管理工具-Swarm部署记录,下面重点说下Swarm基于多主机容器通信的覆盖网络 在Docker版本1.12之后swarm模式原生支持覆盖网络(overlay networks) ...
- 网易2018.03.27算法岗,三道编程题100%样例AC题解
博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/8660814.html特别不喜欢那些随便转载别人的原创文章又不给 ...
- 【BUAA软件工程】第一次阅读作业
BUAA软件工程 第一次阅读作业 项目 内容 这个作业属于哪个课程? 北航软工 这个作业的要求在哪里? 第一次个人作业 我在这个课程的目标是? 学习高效严谨的软件工程开发过程,建立团队意识 这个作业在 ...
- linux和Mac上安装composer
使用命令行方式,可以直接使用下面的命令,顺序执行: php -r "copy ('https://getcomposer.org/installer','composer-setup.php ...
- jmeter作用域规则
创建测试计划时,会创建一个有序的一系列将要被执行的请求列表,这些请求通常被组织在有序的控制器下 一些控制器会影响包含在它下面的请求顺序 ,这些特殊的控制器可以参考这里:the component re ...
- 近端梯度算法(Proximal Gradient Descent)
L1正则化是一种常用的获取稀疏解的手段,同时L1范数也是L0范数的松弛范数.求解L1正则化问题最常用的手段就是通过加速近端梯度算法来实现的. 考虑一个这样的问题: minx f(x)+λg(x) x ...
- 10 月 30 日新款 Mac mini 有望与新款 iPad Pro 一起发布
苹果最新款的 Mac mini 是在 2014 年 10 月推出的版本,到现在已经过了 4 年.分析师郭明錤和彭博社的 Mark Gurman 都表示苹果会在今年晚些时候发布新款 Mac mini. ...
- MyBatis:一对一关联查询
MyBatis从入门到放弃三:一对一关联查询 前言 简单来说在mybatis.xml中实现关联查询实在是有些麻烦,正是因为起框架本质是实现orm的半自动化. 那么mybatis实现一对一的关联查询则是 ...