luogu 3295[SCOI2016]萌萌哒

Posted encodetalker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu 3295[SCOI2016]萌萌哒相关的知识,希望对你有一定的参考价值。

题目链接:luogu 3295

很明显的想法是用并查集维护最后有几个块内的数字必须相等,设最后有\(cnt\)个联通块,那么答案就是\(9\times10^{cnt-1}\)

暴力维护并查集是\(O(nlen)\)的,显然超时,考虑优化

\(f_{i,j}\)表示区间\([i,i+2^j-1]\)的编号,编号相同则区间中元素值相同

考虑将一段区间\((l_1,r_1)\)\((l_2,r_2)\)合并时,将每个区间拆成\(log\)段,合并\((l_1,l_1+2^k-1)\)\((l_2,l_2+2^k-1)\)

最后像线段树标记下放一样将\(f_{i,j}\)的值下放到\(f_{i+2^j-1,j-1}\)\(f_{i+2^j,j-1}\)

刚开始一只啊在想线段树优化然后。。。就凉了

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x)&(-x)
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=a;i>=b;i--)
#define maxd 1000000007
typedef long long ll;
const int N=100000;
const double pi=acos(-1.0);
int n,m,fa[500100][20];

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

int find(int x,int y)
{
    if (fa[x][y]==x) return x;
    fa[x][y]=find(fa[x][y],y);
    return fa[x][y];
}

int main()
{
    n=read();m=read();
    rep(i,1,n)
        rep(j,0,19) fa[i][j]=i;
    rep(i,1,m)
    {
        int l1=read(),r1=read(),l2=read(),r2=read();
        int pos1=l1,pos2=l2;
        per(j,19,0)
        {
            if (pos1+(1<<j)-1<=r1)
            {
                int fa1=find(pos1,j),fa2=find(pos2,j);
                if (fa1!=fa2) fa[fa1][j]=fa2;
                pos1+=(1<<j);pos2+=(1<<j);
            }
        }
    }
    per(j,19,1)
    {
        int i;
        for (i=1;i+(1<<j)-1<=n;i++)
        {
            int fa1=find(i,j),fa2=find(i,j-1);
            fa[fa2][j-1]=find(fa1,j-1);
            int fa3=find(i+(1<<(j-1)),j-1);
            fa[fa3][j-1]=find(fa1+(1<<(j-1)),j-1);
        }
    }
    ll ans=1;
    rep(i,1,n)
    {
        if (fa[i][0]==i) 
        {
            if (ans==1) ans=(ans*9)%maxd;
            else ans=(ans*10)%maxd;
        }
    }
    printf("%lld",ans);
    return 0;
}
    

以上是关于luogu 3295[SCOI2016]萌萌哒的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P3295 [SCOI2016]萌萌哒

[Luogu P3295][SCOI 2016]萌萌哒

luogu P3295 [SCOI2016]萌萌哒 |倍增+并查集

P3295 [SCOI2016]萌萌哒

P3295 [SCOI2016]萌萌哒——倍增并查集

[SCOI2016]萌萌哒