zoukankan      html  css  js  c++  java
  • 洛谷P3295 [SCOI2016]萌萌哒

    题目描述:

     题意:给你一个长度和多个限制,限制指给定的两个区间内的值必须相等,问一共有几种情况。

    哪里萌萌哒了

    思路分析:我们能想到的最暴力的思路应该就是用并查集了,每给定两个区间,我们就把这两个区间上相应的点都并在一起,来表示它们的值相等,最后统计一下一共有多少个并查集就行了,答案就是9*10^(n-1)(n是并查集数量),因为第一个数不能为0,所以只有九种情况。

    但这样是一定会超时的,于是我们来想办法进行优化,看到区间,你想到了什么?ST表?线段树?对了,这道题我们就可以用ST表的思路来进行优化,我们在进行并查集时可以用p[i][j]表示以i为起点的点,向后2^j的长度的区间,这样在合并时就不用再一个点一个点的合并了,就相当于对区间进行了二进制拆分。但是我们这样并不能解决输出的问题,因为此时每个点都被绑在区间上,没有自己的并查集,于是我们就需要将每个点再和它区间的祖先进行合并,这样之后就可以再统计并查集的数目进行计算输出了。其他细节详见注释。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 typedef long long ll;
     5 const int N=1e5+10;
     6 const int Max=21;
     7 const int Mod=1000000007;
     8 int fa[N][Max];
     9 int find(int x,int y){//查找p[x][y]的祖先 
    10     if(fa[x][y]==x) return x;
    11     return fa[x][y]=find(fa[x][y],y);
    12 }
    13 void merge(int x,int y,int i){//合并 
    14     x=find(x,i);y=find(y,i);
    15     if(x!=y){
    16         fa[x][i]=y;
    17     }
    18 }
    19 int main(){
    20     int n,m;
    21     scanf("%d%d",&n,&m);
    22     for(int i=1;i<=n;++i)  //并查集初始化 
    23         for(int j=0;j<Max;++j)
    24             fa[i][j]=i;
    25     for(int i=1;i<=m;++i){
    26         int l1,l2,r1,r2;
    27         scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
    28         for(int j=Max-1;~j;--j){//对拆出来的每一段进行合并 
    29             if(l1+(1<<j)-1<=r1){
    30                 merge(l1,l2,j);
    31                 l1+=(1<<j);l2+=(1<<j);//走下一段 
    32             }
    33         }
    34     }
    35     for(int j=Max-1;j;--j){  //将祖先分到每个区间的节点上 
    36         for(int i=1;i+(1<<j)-1<=n;++i){
    37             merge(i,find(i,j),j-1);
    38             merge(i+(1<<j-1),find(i,j)+(1<<j-1),j-1);
    39         }
    40     }
    41     int num=0;
    42     ll ans=9;
    43     for(int i=1;i<=n;++i) //计算答案 
    44         if(find(i,0)==i) num++;
    45     for(int i=1;i<num;++i){
    46         ans=(ans*10)%Mod;
    47     }
    48     printf("%lld
    ",ans);
    49     return 0;
    50 }
    View Code
  • 相关阅读:
    【BZOJ-3712】Fiolki LCA + 倍增 (idea题)
    【BZOJ-1941】Hide and Seek KD-Tree
    【BZOJ-2400】Spoj839Optimal Marks 最小割 + DFS
    【BZOJ-3709】Bohater 贪心
    【BZOJ-2342】双倍回文 Manacher + 并查集
    【BZOJ-3790】神奇项链 Manacher + 树状数组(奇葩) + DP
    【BZOJ-4568】幸运数字 树链剖分 + 线性基合并
    【BZOJ-4520】K远点对 KD-Tree + 堆
    【BZOJ-4127】Abs 树链剖分 + 线段树 (有趣的姿势)
    【BZOJ-2648&2716】SJY摆棋子&天使玩偶 KD Tree
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/12842124.html
Copyright © 2011-2022 走看看