「SCOI2016」萌萌哒
「SCOI2016」萌萌哒
题目描述
一个长度为 \(n\) 的大数,用 \(S_1S_2S_3 \ldots S_n\) 表示,其中 \(S_i\) 表示数的第 \(i\) 位,\(S_1\) 是数的最高位,告诉你一些限制条件,每个条件表示为四个数 $(l_1, r_1, l_2, r_2) $,即两个长度相同的区间,表示子串 $S_{l_1}S_{l_1 + 1}S_{l_1 + 2} \ldots S_{r_1} $与 \(S_{l_2}S_{l_2 + 1}S_{l_2 + 2} \ldots S_{r_2}\)完全相同。
比如 \(n = 6\) 时,某限制条件 $(l_1 = 1, r_1 = 3, l_2 = 4, r_2 = 6) $,那么 \(123123\)、\(351351\) 均满足条件,但是 \(12012\)、\(131141\) 不满足条件,前者数的长度不为 \(6\),后者第二位与第五位不同。问满足以上所有条件的数有多少个。
\(1 \leq n \leq 10^5, 1 \leq m \leq 10^5,1 \leq li_1,ri_1,li_2,ri_2 \leq n\) 并且保证 ${r_i}_1 - {l_i}_1 = {r_i}_2 - {l_i}_2 $
解题思路 :
观察发现,限制条件的本质是使得一些位置只能填同样的字符,我们不妨把限制在一起的位置看做点,在它们之间连一条边
那么统一联通块里面的位置就只能填同一字符了,所以设联通快数为 \(x\) ,那么答案就是 \(9 \times 10^{x-1}\) (第一位不能填 \(0\) ,所以少一种选择)
于是就有一个暴力的做法,用并查集维护联通块,每次对于一组限制 \(l_1, r_1, l_2, r_2\) ,暴力将两个区间的对应点合并,复杂度 \(O(n^2logn)\)
考虑怎么优化并查集的合并,由于是区间问题,所以很容易就想到用线段树或者 \(st\) 表来维护
每次把可以询问区间拆成 \(log\) 个区间,区间与区间之间进行连边,难点在于最后怎么将区间之间的合并转化到点上
由于题目只需要最终询问一次,不妨利用 \(lazytag\) 的思想,对每一种长度的区间用一个并查集来维护,最后算答案的时候将合并信息下传
具体来讲,考虑 \(st\) 表的做法:设 \(fa(i,j)\) 表示左端点为 \(i\) 的长度为 \(2 ^ j\) 的区间所在集合的 \(root\) 的左端点
那么下传信息的时候只需要 \((i, j-1), (i+2^{j-1},j-1)\) 分别和 \((fa(i, j), j - 1)\) 合并即可,最后统计一下 \((i, 0)\) 的联通块数 ,总复杂度 \(O(nlog^2n)\)
/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 500005, Mod = 1000000007;
int fa[N][21], n, m;
inline int ask(int x, int y){
return x == fa[x][y] ? x : fa[x][y] = ask(fa[x][y], y);
}
int main(){
read(n), read(m);
for(int i = 1; i <= n; i++)
for(int j = 0; j <= 20; j++) fa[i][j] = i;
while(m--){
int l1, r1, l2, r2;
read(l1), read(r1), read(l2), read(r2);
int ps1 = l1, ps2 = l2;
for(int i = 20; ~i; i--)
if(ps1 + (1 << i) - 1 <= r1){
int p = ask(ps1, i), q = ask(ps2, i);
if(p != q) fa[p][i] = q;
ps1 += (1 << i), ps2 += (1 << i);
}
}
for(int j = 20; j; j--)
for(int i = 1; i + (1 << j) - 1 <= n; i++){
int p = ask(i, j), q = ask(i, j - 1);
fa[q][j-1] = ask(p, j - 1);
p = ask(i, j), q = ask(i + (1 << j - 1), j - 1);
fa[q][j-1] = ask(p + (1 << j - 1), j - 1);
}
ll res = 1ll;
for(int i = 1; i <= n; i++)
if(fa[i][0] == i) (res *= (res == 1ll) ? 9ll : 10ll) %= Mod;
cout << res;
return 0;
}
「SCOI2016」萌萌哒的更多相关文章
- 「SCOI2016」萌萌哒 解题报告
「SCOI2016」萌萌哒 这思路厉害啊.. 容易发现有个暴力是并查集 然后我想了半天线段树优化无果 然后正解是倍增优化并查集 有这个思路就简单了,就是开一个并查集代表每个开头\(i\)每个长\(2^ ...
- 【LOJ】#2014. 「SCOI2016」萌萌哒
题解 这个题好妙啊 首先我们发现,如果我们可以暴力,就是把相同的元素拿并查集合起来,最后统计集合个数\(cnt\) 答案是\(9\*10^{cnt - 1}\) 然而我们做不到= = 我们可以用倍增的 ...
- loj2014 「SCOI2016」萌萌哒
神tm st表+并查集 #include <iostream> #include <cstdio> #include <cmath> using namespace ...
- 题解 「SCOI2016」萌萌哒
link Description 一个长度为 $ n $ 的大数,用 $ S_1S_2S_3 \ldots S_n $表示,其中 $ S_i $ 表示数的第 $ i $ 位,$ S_1 $ 是数的最高 ...
- LOJ#2014「SCOI2016」萌萌哒(倍增,并查集优化连边)
题面 点此看题 题意很明白,就不转述了吧. 题解 题目相当于告诉了我们若干等量关系,每个限制 l 1 , r 1 , l 2 , r 2 \tt l_1,r_1,l_2,r_2 l1,r1,l2 ...
- 「SCOI2016」围棋 解题报告
「SCOI2016」围棋 打CF后困不拉基的,搞了一上午... 考虑直接状压棋子,然后发现会t 考虑我们需要上一行的状态本质上是某个位置为末尾是否可以匹配第一行的串 于是状态可以\(2^m\)压住了, ...
- 「SCOI2016」妖怪 解题报告
「SCOI2016」妖怪 玄妙...盲猜一个结论,然后过了,事后一证,然后假了,数据真水 首先要最小化 \[ \max_{i=1}^n (1+k)x_i+(1+\frac{1}{k})y_i \] \ ...
- 「SCOI2016」美味 解题报告
「SCOI2016」美味 状态极差无比,一个锤子题目而已 考虑每次对\(b\)和\(d\)求\(c=d \ xor \ (a+b)\)的最大值,因为异或每一位是独立的,所以我们可以尝试按位贪心. 如果 ...
- 「SCOI2016」背单词 解题报告
「SCOI2016」背单词 出题人sb 题意有毒 大概是告诉你,你给一堆n个单词安排顺序 如果当前位置为x 当前单词的后缀没在这堆单词出现过,代价x 这里的后缀是原意,但不算自己,举个例子比如abc的 ...
随机推荐
- 使用TortoiseGit时如何实现SSH免密码登录
1. Git配置 连接GIT服务器使用的是SSH连接,因此无密码登录,需要使用公钥和私钥. 1) 生成公钥/私钥 在Git Shell中输入ssh-keygen命令,直接回车使用默认 ...
- 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集
[题目]D. Best Edge Weight [题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1&l ...
- bzoj 1143 二分图最大独立集
我们可以将一个点拆成两个点x,y,那么如果存在一条i->j的路径,我们就连接xi,yj,那么答案就是n-最大匹配数. 因为i->j所以对于i与j只能选一个,那么我们只需要求出来二分图的最大 ...
- 南邮综合题writeup
http://teamxlc.sinaapp.com/web3/b0b0ad119f425408fc3d45253137d33d/index.php fuckjs直接console得到地址 http: ...
- 36 - 网络编程-TCP编程
目录 1 概述 2 TCP/IP协议基础 3 TCP编程 3.1 通信流程 3.2 构建服务端 3.3 构建客户端 3.4 常用方法 3.4.1 makefile方法 3.5 socket交互 3.4 ...
- 【swupdate文档 三】SWUpdate: 嵌入式系统的软件升级
SWUpdate: 嵌入式系统的软件升级 概述 本项目被认为有助于从存储媒体或网络更新嵌入式系统.但是,它应该主要作为一个框架来考虑,在这个框架中可以方便地向应用程序添加更多的协议或安装程序(在SWU ...
- makefile初步制作,arm-linux- (gcc/ld/objcopy/objdump)详解【转】
转自:http://www.cnblogs.com/lifexy/p/7065175.html 在linux中输入vi Makefile 来实现创建Makefile文件 注意:命令行前必须加TAB键 ...
- 338.Counting Bits---位运算---《剑指offer》32
题目链接:https://leetcode.com/problems/counting-bits/description/ 题目大意:求解从0到num的所有数的二进制表示中所有1的个数. 法一:暴力解 ...
- Python 中的闭包与装饰器
闭包(closure)是函数式编程的重要的语法结构.闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性. 如果在一个内嵌函数里,对在外部函数内(但不是在全局作用域)的变量进行引用,那么内嵌函数 ...
- HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题目大意:有n个空花瓶,有两种操作: 操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B ...