zoukankan      html  css  js  c++  java
  • luogu 3295[SCOI2016]萌萌哒

    题目链接:luogu 3295

    很明显的想法是用并查集维护最后有几个块内的数字必须相等,设最后有(cnt)个联通块,那么答案就是(9 imes10^{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;
    }
    	
    
    
  • 相关阅读:
    JavaScript 对象
    Java条件语句
    函数的使用注意事项:
    函数的特点
    函数的格式
    for循环
    break和continue的区别和作用
    注意事项
    CSS浮动清除的方法
    转:Oracle 中union的用法
  • 原文地址:https://www.cnblogs.com/encodetalker/p/10801334.html
Copyright © 2011-2022 走看看