【洛谷3295】[SCOI2016]萌萌哒

传送门

倍增并查集。

//Twenty
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int mod=1e9+7;
int f[maxn][20],n,m;

void read(int &ret) {
    int f=1; ret=0; char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0'; ret*=f;
}

int find(int x,int l) {
    return x==f[x][l]?x:f[x][l]=find(f[x][l],l);
}

void link(int u,int v,int l) {
    if(find(u,l)==find(v,l)) return;
    f[f[u][l]][l]=f[v][l];
}

void init() {
    read(n); read(m);
    for(int i=1;i<=n;i++)
        for(int j=0;j<20;j++)
            f[i][j]=i;
    for(int i=1;i<=m;i++) {
        int a,b,c,d;
        read(a); read(b);
        read(c); read(d);
        for(int j=19;j>=0;j--) {
            if(a+(1<<j)-1<=b) {
                link(a,c,j);
                a+=(1<<j); 
                c+=(1<<j);
            }
        }
    }
    for(int j=19;j>=1;j--) {
        for(int i=1;(i+(1<<j)-1)<=n;i++) {
            link(i,find(i,j),j-1);
            link(i+(1<<j-1),f[i][j]+(1<<j-1),j-1);
        }
    }
    int cnt=0;
    LL ans=9;
    for(int i=1;i<=n;i++) 
        if(find(i,0)==i) cnt++;
    for(int i=1;i<cnt;i++) {
        (ans*=10)%=mod;
    }
    printf("%lld
",ans);
}

int main()
{
    init();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Achenchen/p/7725586.html