您的位置:首页 > 其它

BZOJ 4569: [Scoi2016]萌萌哒

2017-10-18 09:56 435 查看
妙啊 我好菜啊

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

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+2,mod=1e9+7;
char B[1<<14],*S=B,*T=B;
#define gc (S==T&&(T=(S=B)+fread(B,1,1<<14,stdin),S==T)?-1:*S++)
inline int read(){
int x=0,f=1; char ch=gc;
while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=gc;}
while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=gc;}
return x*f;
}
int f
[17],F[N*17],b[17],px[N*17],py[N*17],tot;
bool v[N*17];
int fa(int x){return x==F[x]?x:F[x]=fa(F[x]);}
void merge(int x,int y){x=fa(x),y=fa(y),F[x]=y;}
int main(){
int i,j,n=read(),m=read(); b[0]=1,tot=0;
if(n==1)return puts("0"),0;
for(i=1;i<17;++i) b[i]=b[i-1]<<1;
for(i=1;i<=n;++i)
for(j=0;j<17;++j)
if(i+b[j]-1<=n)f[i][j]=++tot,F[tot]=tot,px[tot]=i,py[tot]=j;
else break;
for(i=1;i<=m;++i){
int l1=read(),r1=read(),l2=read(),r2=read();
for(j=16;~j;--j)
if(l1+b[j]-1<=r1) merge(f[l1][j],f[l2][j]),l1+=b[j],l2+=b[j];
}
for(j=16;j;--j)
for(i=1;i<=n;++i) if(f[i][j]){
int u=fa(f[i][j]),x=px[u];
merge(f[i][j-1],f[x][j-1]);
merge(f[i+b[j-1]][j-1],f[x+b[j-1]][j-1]);
}
int ans=9,c=-1;
for(i=1;i<=n;++i) if( !v[f[i][0]=fa(f[i][0])] )v[f[i][0]]=1,++c;
while(c--)ans=1ll*ans*10%mod;
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: