zoukankan      html  css  js  c++  java
  • 【LOJ】#2014. 「SCOI2016」萌萌哒

    题解

    这个题好妙啊
    首先我们发现,如果我们可以暴力,就是把相同的元素拿并查集合起来,最后统计集合个数(cnt)
    答案是(9*10^{cnt - 1})
    然而我们做不到= =
    我们可以用倍增的思想,类似st表,一次合并两个长度为(2^l)的区间
    然后再从区间长度最长往下下放,从长到短遍历,就下放一层,之后会继续遍历到这层然后下放
    最后统计集合个数,复杂度是(O(n log n))

    代码

    #include <bits/stdc++.h>
    //#define ivorysi
    #define MAXN 100005
    typedef long long int64;
    typedef unsigned int u32;
    using namespace std;
    const int MOD = 1000000007;
    int fa[MAXN * 25];
    int st[MAXN][20],cnt = 0;
    int log_2[MAXN],n,m;
    int lc[MAXN * 25],rc[MAXN * 25];
    int getfa(int x) {return x == fa[x] ? x : fa[x] = getfa(fa[x]);}
    void merge(int x,int y) {
        if(getfa(x) == getfa(y)) return;
        fa[getfa(x)] = getfa(y);
    }
    void Init() {
        scanf("%d%d",&n,&m);
        for(int i = 2 ; i <= n ; ++i) log_2[i] = log_2[i / 2] + 1;
        for(int j = log_2[n] ; j >= 0 ; --j) {
    	for(int i = 1 ; i + (1 << j) - 1 <= n ; ++i) {
    	    st[i][j] = ++cnt;
    	    fa[cnt] = cnt;
    	}
        }
        for(int j = 1 ; j <= log_2[n] ; ++j) {
    	for(int i = 1 ; i + (1 << j) - 1 <= n ; ++i) {
    	    lc[st[i][j]] = st[i][j - 1];
    	    rc[st[i][j]] = st[i + (1 << j - 1)][j - 1];
    	}
        }
    }
    void Solve() {
        int s1,e1,s2,e2;
        while(m--) {
    	scanf("%d%d%d%d",&s1,&e1,&s2,&e2);
    	int l = log_2[e1 - s1 + 1];
    	merge(st[s1][l],st[s2][l]);
    	merge(st[e1 - (1 << l) + 1][l],st[e2 - (1 << l) + 1][l]);
        }
        for(int j = 1; j <= cnt; ++j) {
    	if(!lc[j] || !rc[j]) continue;
    	int t;
    	if((t = getfa(j)) != j) {
    	    merge(lc[j],lc[t]);
    	    merge(rc[j],rc[t]);
    	}
        }
        int sum = 0;
        for(int i = 1 ; i <= n ; ++i) {
    	if(getfa(st[i][0]) == st[i][0]) ++sum;
        }
        int64 ans = 9;
        for(int i = 1 ; i < sum ; ++i) ans = ans * 10 % MOD;
        printf("%lld
    ",ans);
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    
  • 相关阅读:
    u盘安装ubuntu10.04 、11.04 server 分类: arm-linux-Ubuntu 2013-08-12 15:47 504人阅读 评论(0) 收藏
    linux下的framebuffer显示图片 分类: arm-linux-Ubuntu 2013-08-12 15:43 506人阅读 评论(0) 收藏
    Sql Server专题:SQL 经典实例
    1054 求平均值 (20 分)
    1052 卖个萌 (20 分)
    1053 住房空置率 (20 分)
    1050 螺旋矩阵 (25 分
    1051 复数乘法 (15 分)
    1049 数列的片段和 (20 分)
    1046 划拳 (15 分)
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9155831.html
Copyright © 2011-2022 走看看