码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj4569: [Scoi2016]萌萌哒(ST表+并查集)

时间:2017-10-16 09:39:43      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:ring   mod   names   while   ace   getc   str   none   char   

  好喵喵的题

  将一个要求用ST表分割成logn个要求,如果把f[i][j]和f[u][v]在同一个集合,那么f[i][j-1]和f[u][v-1],f[i+2^(j-1)][j-1]和f[u][u+2^(v-1)][v-1]就并到同一个集合,最后只需要计算f[i][0]不同的集合数cnt,则答案为9*10^(cnt-1)

技术分享
#include<iostream> 
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath> 
#include<algorithm> 
using namespace std;
const int maxn=200010,mod=1e9+7;
int n,m,l1,r1,l2,r2,tot,ans,cnt;
int mi[maxn],f[maxn][20],posi[maxn*20],posj[maxn*20],fa[maxn*20];
bool v[maxn*20];
inline void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<0||c>9)c==-&&(f=-1),c=getchar();
    while(c<=9&&c>=0)k=k*10+c-0,c=getchar();
    k*=f;
}
int gf(int x){return fa[x]==x?x:fa[x]=gf(fa[x]);}
void merge(int x,int y){x=gf(x);y=gf(y);fa[x]=y;}
int main()
{
    read(n);read(m);
    if(n==1)return puts("10"),0;
    mi[0]=1;for(int i=1;i<=18;i++)mi[i]=mi[i-1]<<1;
    for(int i=1;i<=n;i++)
    for(int j=0;j<=18;j++)
    f[i][j]=++tot,posi[tot]=i,posj[tot]=j,fa[tot]=tot;
    for(int i=1;i<=m;i++)
    {
        read(l1);read(r1);read(l2);read(r2);
        for(int j=18;j>=0;j--)
        if(l1+mi[j]-1<=r1)
        {
            merge(f[l1][j],f[l2][j]);
            l1+=mi[j];l2+=mi[j];
        }
    }
    for(int j=18;j;j--)
    for(int i=1;i<=n;i++)
    {
        int now=gf(f[i][j]);
        int u=posi[now],v=posj[now];
        merge(f[i][j-1],f[u][v-1]);
        merge(f[i+mi[j-1]][j-1],f[u+mi[v-1]][v-1]);
    }
    for(int i=1;i<=n;i++)if(!v[fa[f[i][0]]=gf(fa[f[i][0]])])v[fa[f[i][0]]]=1,cnt++;
    ans=9;for(int i=1;i<cnt;i++)ans=1ll*ans*10%mod;
    printf("%d\n",ans);
}
View Code

 

bzoj4569: [Scoi2016]萌萌哒(ST表+并查集)

标签:ring   mod   names   while   ace   getc   str   none   char   

原文地址:http://www.cnblogs.com/Sakits/p/7675360.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!