zoukankan      html  css  js  c++  java
  • 题解 「SCOI2016」萌萌哒

    link

    Description

    一个长度为 $ 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 $,后者第二位与第五位不同。问满足以上所有条件的数有多少个。

    (nle 10^5)

    Solution

    可以想到,我们用 (f_{i,j}) 表示 ([i,i+2^j-1]) 这一段区间,然后每次合并两个区间就相当于合并 (f_{l1,k},f_{l2,k}) 以及 (f_{r1-2^k+1,k},f_{r2-2^k+1,k})

    然后我们还需要将儿子也下传一下合并标记即可。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define mod 1000000007
    #define MAXN 100005
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
    template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
    
    int n,m,tot,lg[MAXN],f[MAXN][21],ls[MAXN * 21],rs[MAXN * 21],fa[MAXN * 21];
    
    int findSet (int x){return fa[x] == x ? x : fa[x] = findSet (fa[x]);}
    void unionSet (int x,int y){
    	x = findSet (x),y = findSet (y);
    	if (x == y) return ;
    	fa[y] = x;
    }
    
    signed main(){
    	read (n,m);
    	for (Int i = 2;i <= n;++ i) lg[i] = lg[i >> 1] + 1;
    	for (Int j = 0;(1 << j) <= n;++ j)
    		for (Int i = 1;i + (1 << j) - 1 <= n;++ i)
    			f[i][j] = ++ tot,fa[tot] = tot;
    	for (Int j = 1;(1 << j) <= n;++ j)
    		for (Int i = 1;i + (1 << j) - 1 <= n;++ i)
    			ls[f[i][j]] = f[i][j - 1],rs[f[i][j]] = f[i + (1 << j - 1)][j - 1];
    	for (Int i = 1;i <= m;++ i){
    		int l1,r1,l2,r2;read (l1,r1,l2,r2);
    		int k = lg[r1 - l1 + 1];
    		unionSet (f[l1][k],f[l2][k]);
    		unionSet (f[r1 - (1 << k) + 1][k],f[r2 - (1 << k) + 1][k]);
    	}
    	for (Int j = lg[n];j >= 1;-- j)
    		for (Int i = 1;i + (1 << j) - 1 <= n;++ i){
    			int t = findSet (f[i][j]);
    			if (t == f[i][j]) continue;
    			unionSet (ls[t],ls[f[i][j]]);
    			unionSet (rs[t],rs[f[i][j]]);
    		}
    	int cnt = n,res = 9;
    	for (Int i = 1;i <= n;++ i) if (findSet (f[i][0]) != f[i][0]) cnt --;
    	for (Int i = 1;i < cnt;++ i) res = 1ll * res * 10 % mod;
    	write (res),putchar ('
    ');
    	return 0;
    }
    
  • 相关阅读:
    在 SQL2005 使用行转列或列转行
    JOIN 和 WHERE?简单的问题也有学问。
    完整的获取表结构语句
    经典背景音乐收集
    interface 是什么类型?
    WMI使用集锦
    存储过程+游标,第一回开发使用
    Sql Server 基本语句汇总
    PowerDesigner 设置各项变量参数的路径
    测试
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/15184387.html
Copyright © 2011-2022 走看看