又切一道紫题!!!

成功的(看了一吨题解之后),我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表的更多相关文章

  1. bzoj 4569 [Scoi2016]萌萌哒 并查集 + ST表

    题目链接 Description 一个长度为\(n\)的大数,用\(S_1S_2S_3...S_n\)表示,其中\(S_i\)表示数的第\(i\)位,\(S_1\)是数的最高位,告诉你一些限制条件,每 ...

  2. luogu3295 萌萌哒 (并查集+ST表)

    如果给相同的位置连边,最后联通块数是n,最后答案就是$9*10^{n-1}$ 但直接连边是$O(n^2)$的 所以事先处理出一个ST表,每次O(1)地给那个ST表连边 最后再一点一点下放,就是把在这层 ...

  3. 【洛谷3865】 【模板】ST表(猫树)

    传送门 洛谷 Solution 实测跑的比ST表快!!! 这个东西也是\(O(1)\)的,不会可以看我上一篇Blog 代码实现 代码戳这里

  4. 洛谷P3295 萌萌哒 [SCOI2016] 倍增+并查集

    正解:倍增+并查集 解题报告: 传送门! 首先不难想到暴力?就考虑把区间相等转化成对应点对相等,然后直接对应点连边,最后求有几个连通块就好辣 然后看下复杂度,修改是O(n2)查询是O(n),就比较容易 ...

  5. 洛谷P4092树——并查集

    题目:https://www.luogu.org/problemnew/show/P4092 利用并查集,倒序离线,那么从倒序来看被撤销标记的点就再也不会被标记,所以用并查集跳过: 莫名其妙的WA,调 ...

  6. 洛谷P2391 白雪皑皑(并查集)

    题目背景 “柴门闻犬吠,风雪夜归人”,冬天,不期而至.千里冰封,万里雪飘.空中刮起了鸭毛大雪.雪花纷纷,降落人间. 美能量星球(pty 在 spore 上的一个殖民地)上的人们被这美景所震撼.但是 p ...

  7. 洛谷P3958 奶酪 并查集

    两个空洞可互达当且仅当两个空洞相切,即球心距离小于等于球的直径. 一一枚举两个可互达的空洞,并用并查集连起来即可. Code: #include<cstdio> #include<c ...

  8. 洛谷 P3958 奶酪 并查集

    目录 题面 题目链接 题面 题目描述 输入输出格式 输入格式 输出格式: 输入输出样例 输入样例 输出样例 说明 思路 AC代码 总结 题面 题目链接 P3958 奶酪 题面 题目描述 现有一块大奶酪 ...

  9. 洛谷 P2391.白雪皑皑 (并查集,思维)

    题意:有\(n\)个点,对这些点进行\(m\)次染色,第\(i\)次染色会把区间\((i*p+q)\ mod\ N+1\)和\((i*q+p)\ mod\ N+1\)之间的点染成颜色\(i\),问最后 ...

随机推荐

  1. item 7:当创建对象的时候,区分()和{}的使用

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 从不同的角度来看,在C++11中,对象初始化拥有多种语法选择,这体 ...

  2. 记录网件r6220路由器登录配置

    1.设置本地连接为自动获取ip和DNS地址 2.使用网线连接电脑和路由器的LAN口 3.http://routerlogin.net/BRS_index.htm 4.用户名和密码: admin pas ...

  3. redis持久化策略梳理及主从环境下的策略调整记录

    redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化.可以不定期的通过异步方式保存到磁盘上(即“半持久化模式”):也可以把每一次数据变化都写入到一个A ...

  4. Linux内核分析作业五

    扒开系统调用的三层皮(下) 给MenuOS增加time和time-asm命令 步骤 rm menu -rf //强制删除 git clone http://github.com/menging/men ...

  5. github个人心得

    github真难全是英语真费劲 以后要好好学习英语 https://github.com/huangjingyi/test

  6. C#-ToString格式化

    Int.ToString(format): 格式字符串采用以下形式:Axx,其中 A 为格式说明符,指定格式化类型,xx 为精度说明符,控制格式化输出的有效位数或小数位数,具体如下: 格式说明符 说明 ...

  7. PAT 1081 检查密码

    https://pintia.cn/problem-sets/994805260223102976/problems/994805261217153024 本题要求你帮助某网站的用户注册模块写一个密码 ...

  8. 命令行方式(SSH or powershell )远程windows server

    1. 使用ssh的方式远程登录window server 网上找到的方法大部分是freesshd 或者是Copsshd这样的工具 方式就是 下载安装文件,然后服务器端进行安装: 安装完成之后作为服务启 ...

  9. [日常工作]非Windows Server 系统远程经常断以及提高性能的方法

    1. 公司内有不少windows xp windows 7 这样的操作系统的机器在机房里面用来跑自动化脚本或者是其他用处. 经常有人反馈机器过一段时间连不上, 其实这一点是一个非常小的地方 很多机器上 ...

  10. Python表达式与运算符

    表达式与运算符 Python语言支持以下类型的运算符: 算术运算符 比较(关系)运算符 赋值运算符 逻辑运算符 位运算符 成员运算符 身份运算符 运算符优先级 算术运算符 运算符 描述 + 加 - 两 ...