[Bzoj4569] [lojの#2014] [Scoi2016] Mengmengピリダジン

説明

長さ\(\ N-)を有する多数で、\(S1S2S3 ... Snの\) \(Siは\)の数を表し\(Iは\)ビット、\(SLは\)最大数でありますビットは、それぞれが4番、として表され、あなたにいくつかの制約条件を伝える\(L1 \)、\ (R1 \)、\ (L2 \)、\ (R2 \) つまり、2つの長さと同じ範囲、表現部分文字列\(SL1 \) \(SL1。1 + \) \(SL1 + 2 \) \(... \) \(SR1 \)\(SL2 \) \(SL2 + 1 \) \(SL2 + 2 \) \(... \) \(のSr2 \)とまったく同じ。例えば\(N = 6 \)制約\(L1 = 1 \)、\ (R1 = 3 \)、\ (4 L2 = \)、\ (R2 = 6 \)条件が123123,351351満たされているが、12012,131141条件が満たされていない、そして、元の長さは、第二及び第五の異なる数6ありません。以上のいくつかは、すべての条件を満たしているどのように多く尋ねました。

入力

最初の2つの行番号\(\ N-)\(m個\)多数の長さ、及び制約の数を表します。\(m個\)ライン、最初のため\(Iは\)番号の行、4 \(たLi1 \で)、\ (RI1 \)、\ (LI2 \)、\ (RI2 \) それぞれ、制限条件に対応する2つの間隔。
\(1 \のLeq N- \のLeq 10 ^ 5 \。)、\ (1 \のLeq M \のLeq 10 ^ 5 \。)、\ (たLi1、RI1 1 \のLeq、LI2、RI2 \のLeq N- \。) ;及び保証するために\を( = RI2-でたLi1-RI1 LI2 \)

出力

すべての条件が満たされ表す数と長さ\(N- \)多数の数は、答えが大きくなるので、出力ダイ回答できる\(9 + 10 ^ 7 \)結果をします。

サンプル入力

4 2

1 2 3 4

3 3 3 3

サンプル出力

90


考え

1つの明白なアイデアは互いに素セット同じ位置し、最大でその暴力で
最後のクエリをどのように多くの互いに素セットで\(X \)ヶ月、最終的な答えがされ(9 \回10 ^ {\ N-1を} \)(MSBをゼロにする)ことはできません
が、明らかにタイムアウトになりました。

でも側を最適化する方法を検討-倍増。
多くの不要な側波帯(例えば、すべての多くの副作用があるかもしれせてあるので、辺の偶数上記過剰な数のノート\(U \)\(V \)やサイズ、リンクする\(N \)はそして有用側の濃度を確認するだけ\(N-1は、\)のストリップが、内部にも多くのエッジ)に
非常に微妙なアプローチはいくつかの新しいポイントを追加することがあることの長さを表し\(2 ^ I \)のをセクション、にやや類似\(ST \)テーブル
するように組み合わされるたび\([L、R] \ ) に分割されている\(O(LOGN)\)セグメント間隔、代表点は、それが対応する間隔
最終分散。オリジナルの代表として\([L1、R1] \ ) と\([L2、R2] \ ) 集中化と、その後のチェックポイントの\([L1、(L1 + R1)>> 1] \) と\ ([L2(L2 + R2 )>> 1] \) とアップ、\([(L1 + R1) >> 1 + 1、R1] \) と\([(L2 + R2) >> 1+ 1、R 2] \)及び最大
合計複雑分散化されている\(O(nlogn)\)
最後に、分散は、セットの数を見て、1点の間隔の長さを表し、それをチェックすることです。
総複雑\(O(LOGN)\)

独創的!フェアリー方法\(\ ORZ)


コード

#include<cstdio>
#include<iostream>
#include<algorithm>

#define P 1000000007

using namespace std;

int read(){
    int x=0;
    char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x;
}

const int N = 100005;

int n,m;
int f[N][18],cnt,ch[18*N][2],fa[N*18];

int getfa(int x) { return x==fa[x] ? x : fa[x]=getfa(fa[x]) ; }
void unit(int x,int y){
    x=getfa(x); y=getfa(y);
    if(x!=y) fa[x]=y; 
}

int Pow_mod(int x,int y){
    int ret=1;
    while(y){
        if(y&1) ret=1ll*ret*x%P;
        x=1ll*x*x%P;
        y>>=1;
    }
    return ret;
}

int main()
{
    n=read(); m=read();
    int l1,l2,r1,r2;
    
    for(int j=0;j<18;j++){
        int l=(1<<j);
        for(int i=1;i+l-1<=n;i++){
            f[i][j]=++cnt;
            if(j==0) continue;
            ch[cnt][0]=f[i][j-1]; ch[cnt][1]=f[i+(l>>1)][j-1]; 
        }
    }
    
    for(int i=1;i<=cnt;i++) fa[i]=i;
    while(m--){
        l1=read(); r1=read(); l2=read(); r2=read();
        for(int i=17;i>=0;i--){
            if(l1+(1<<i)-1>r1) continue;
            unit(f[l1][i],f[l2][i]);
            l1+=(1<<i); l2+=(1<<i);
        }
    }
    
    for(int i=cnt;i>n;i--)
        if(fa[i]!=i){
            unit(ch[fa[i]][1],ch[i][1]);
            unit(ch[fa[i]][0],ch[i][0]);
        }
    
    int ans=0;
    for(int i=1;i<=n;i++) if(fa[i]==i) ans++;
    printf("%d\n",1ll*9*Pow_mod(10,ans-1)%P);
    
    return 0;
}

おすすめ

転載: www.cnblogs.com/lindalee/p/11432041.html