「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」萌萌哒的更多相关文章

  1. 「SCOI2016」萌萌哒 解题报告

    「SCOI2016」萌萌哒 这思路厉害啊.. 容易发现有个暴力是并查集 然后我想了半天线段树优化无果 然后正解是倍增优化并查集 有这个思路就简单了,就是开一个并查集代表每个开头\(i\)每个长\(2^ ...

  2. 【LOJ】#2014. 「SCOI2016」萌萌哒

    题解 这个题好妙啊 首先我们发现,如果我们可以暴力,就是把相同的元素拿并查集合起来,最后统计集合个数\(cnt\) 答案是\(9\*10^{cnt - 1}\) 然而我们做不到= = 我们可以用倍增的 ...

  3. loj2014 「SCOI2016」萌萌哒

    神tm st表+并查集 #include <iostream> #include <cstdio> #include <cmath> using namespace ...

  4. 题解 「SCOI2016」萌萌哒

    link Description 一个长度为 $ n $ 的大数,用 $ S_1S_2S_3 \ldots S_n $表示,其中 $ S_i $ 表示数的第 $ i $ 位,$ S_1 $ 是数的最高 ...

  5. LOJ#2014「SCOI2016」萌萌哒(倍增,并查集优化连边)

    题面 点此看题 题意很明白,就不转述了吧. 题解 题目相当于告诉了我们若干等量关系,每个限制 l 1 , r 1 , l 2 , r 2 \tt l_1,r_1,l_2,r_2 l1​,r1​,l2​ ...

  6. 「SCOI2016」围棋 解题报告

    「SCOI2016」围棋 打CF后困不拉基的,搞了一上午... 考虑直接状压棋子,然后发现会t 考虑我们需要上一行的状态本质上是某个位置为末尾是否可以匹配第一行的串 于是状态可以\(2^m\)压住了, ...

  7. 「SCOI2016」妖怪 解题报告

    「SCOI2016」妖怪 玄妙...盲猜一个结论,然后过了,事后一证,然后假了,数据真水 首先要最小化 \[ \max_{i=1}^n (1+k)x_i+(1+\frac{1}{k})y_i \] \ ...

  8. 「SCOI2016」美味 解题报告

    「SCOI2016」美味 状态极差无比,一个锤子题目而已 考虑每次对\(b\)和\(d\)求\(c=d \ xor \ (a+b)\)的最大值,因为异或每一位是独立的,所以我们可以尝试按位贪心. 如果 ...

  9. 「SCOI2016」背单词 解题报告

    「SCOI2016」背单词 出题人sb 题意有毒 大概是告诉你,你给一堆n个单词安排顺序 如果当前位置为x 当前单词的后缀没在这堆单词出现过,代价x 这里的后缀是原意,但不算自己,举个例子比如abc的 ...

随机推荐

  1. LintCode 532: Reverse Pairs

    LintCode 35: Reverse Linked List 题目描述 翻转一个链表. 样例 给出一个链表1->2->3->null,这个翻转后的链表为3->2->1 ...

  2. Vue 脱坑记

    问题汇总 Q:安装超时(install timeout) 方案有这么些: cnpm : 国内对npm的镜像版本 /* cnpm website: https://npm.taobao.org/ */ ...

  3. 商城项目(ssm+dubbo+nginx+mysql统合项目)总结(3)

    我不会在这里贴代码和详细步骤什么的,我觉得就算我把它贴出来,你们照着步骤做还是会出很多问题,我推荐你们去看一下黑马的这个视频,我个人感觉很不错,一步一步走下来可以学到很多东西.另外,视频和相关文档的话 ...

  4. 用户空间与内核空间数据交换的方式(9)------netlink【转】

    转自:http://www.cnblogs.com/hoys/archive/2011/04/10/2011722.html Netlink 是一种特殊的 socket,它是 Linux 所特有的,类 ...

  5. static作用(修饰函数、局部变量、全局变量)转自http://www.cnblogs.com/stoneJin/archive/2011/09/21/2183313.html

    static作用(修饰函数.局部变量.全局变量) 在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条. (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件 ...

  6. for 、forEach 、 forof、 forin遍历对比

    一.遍历内容的异同 1.for 和 for...in 是针对数组下标的遍历 2.forEach 及 for...of 遍历的是数组中的元素 二.对非数字下标的处理 由于array在js中也是对象中的一 ...

  7. HDU 5936 朋友

    题意为给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1. 在一局游戏开始时,会确定一个节点作为根. 当一方操作时,他们需要先选择一个不为根的点,满足该点到其父亲的边权为1; 然后 ...

  8. linux -j 4

    把源码编译成可执行的二进制文件, 4为服务器内核数

  9. Eloqument 学习

    参考地址:https://d.laravel-china.org/docs/5.5/eloquent#mass-assignment

  10. IP地址及子网--四种IP广播地址

    国际规定:把所有的IP地址划分为 A,B,C,D,E. 类默认子网掩码:A类为 255.0.0.0; B类为 255.255.0.0; C类为 255.255.255.0.子网掩码是一个32位地址,用 ...