test20190814 NOIP2019シミュレーションタイトル

二進木

[問題の説明]
バイナリツリーがかつてありました、私たちは、バイナリツリーを表現するには、次の方法を使用します。

  1. ノードが息子を持っていない場合は、我々は彼を表現するために「0」を使用します。
  2. ノードは、息子を持っており、我々はそれがその人の息子の表現に続いて、「1」の始まりを表し見つけた場合。
  3. ノードは2人の息子を持っている、と我々はそれが「2」の始まりを表し見つけた場合、彼は彼の息子を取るために残さその表現の右の息子が続く、と述べました。

その後、ノードは2人の子供を持っている場合は、各ノードとその子は、同じ色を持つことができない、2:非常に、これらの木は、染め、楽しいKJDHと、それは染色し、非常にルール、非常に賢いですKJDH子どもたちは、同じ色を持つことができません。この古来の木のため、私たちは、各ノードの色を見ることができなかったが、我々は唯一、赤、黄色や白の色で染色KJDHを知っています。私たちは、ほとんどと少なくともどのように多くのノードが白です。この木を知りたいです。

[入力形式
tree.in.と呼ばれるファイルには、入力ファイルのみ1行、文字列、唯一の「0」、「1」、「2」の形、そのツリー構造。

[]出力形式の
出力ファイル名tree.out。出力ファイルは、スペースで区切られた2つの数字が含まれており、白色のノードの最も最小数を表します。

試料1 [O]
tree.in
200は
tree.out
1

サンプル2 [O]
tree.in
1122002010
tree.out
。5 2

[データサイズと一致]
LEN <= 10、データの20%。
LEN <= 2000、データの50%
LEN <= 500000、データの100%まで。ここでlenは読み文字列の長さがあります。

問題の解決策

私は、どのような成果一瞬たいと思います。アナログシーケンスブラケットできるスタック。

そして、知恵の木DPです。

co int N=500000+10;
char str[N];
struct node{int id,val;};
int len,lc[N],rc[N],n;
int main(){
    freopen("tree.in","r",stdin),freopen("tree.out","w",stdout);
    scanf("%s",str+1),len=strlen(str+1);
    stack<node> st;
    for(int i=1;i<=len;++i){
        st.push((node){++n,str[i]-'0'});
        while(st.top().val==0){
            int x=st.top().id;st.pop();
            if(x==1) break;
            int fa=st.top().id;
//          cerr<<"link "<<fa<<" "<<x<<endl;
            lc[fa]?rc[fa]=x:lc[fa]=x;
            --st.top().val;
        }
    }
    dfs(1);
    printf("%d %d\n",max(f[1][0],max(f[1][1],f[1][2])),min(g[1][0],min(g[1][1],g[1][2])));
    return 0;
}

ダンス

[問題の説明]
KJDH i番目のカリスマの1からnまでの番号姉妹、各姉妹が踊っされ、ダンスの妹はあるn個ある IOIの分野でカップを保持し、1日KJDH、彼はn個です姉妹がn *(n + 1)個/合計ジャンプする、彼のために踊ること、お祝いしたかった 2 I〜Jの姉踊りの番号によって、それぞれのダンスを、(1 <= iの= J < <= n)を。

各ホップダンスKJDHは喜びの価値を高めるために非常に喜んでいただけることでしょう、私は〜Jの姉妹ダンスの喜びがの価値向上させることができ、番号
(J-I + 1)分(II + 1、...、A Jを) MAX(IIの+ 1、...、A J

Q KJDH多くの喜びが値、モジュロ十億七に対する答えを増やすことができる方法のn *(n + 1)/ 2個のダンスを通してダンス、後。

[入力形式
dance.inと呼ばれるファイルに。
2入力コモンライン。
1行目は、正の整数nが含まれているn個の妹を示しています。
2行目では、n個のスペースで区切られた正の整数が含ま。12、...、nとカリスマを踊っ各姉妹を表します。

[]出力形式の
出力ファイル名dance.out。
KJDHが喜び値を大きく示す整数を含む全出力ライン、。

試料1 [O]
dance.in
。4
2 1 4 4
dance.out
109

[O]サンプル1は示している
合計6ダンスをジャンプ。(i、j)を持つI〜J姉妹踊る喜び値の数が増加しています。
(1,1)= 4(1,2)= 16(1,3)= 12(1,4)= 16
(2,2)= 16(2,3)8 =(2,4)= 12
( 3,3)1(3,4)= 8 =
(4,4)= 16
全てが109まで加えます。

[データサイズと一致]
2000 = <データの60%を、N;
100データの%、nに- <= 500000,1 <A = I <= 10 8

ChiTongZの問題への解決策

\(J-I + 1 \は ) 答えアウトから取り外さ
\ [\ sum_ {J = 1 } ^ n個の\ sum_ {i = 1} ^ J(J-I + 1)\ maxの(I、J)\ 分(i、j)は\\ = \ sum_ {J = 1} ^ NJ \ sum_ {i = 1} ^ j個の\ MAX(i、j)の\分(i、j)は- \ sum_ {i = 1} ^ N(I-1)\ sum_
{J =} ^ N \ MAX(i、j)の\分(I、J)\] 第2の重みが単調加算記号+スタック・セグメントツリー維持することができます。

単調なスタックは、* max及びセグメントツリー分間隔で、範囲その場合、メンテナンス間隔オーバレイ・マーク、セクションMIN、MAXを覆い、そしてします。私がやって見つけることができます。

時間複雑\(O(N \ N-ログ)\) タイトルヒト定常カード。

#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
    T x=0,w=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*w;
}
template<class T> T read(T&x){
    return x=read<T>();
}
using namespace std;
typedef long long LL;

co int mod=1000000000+7;
il int add(int a,int b){
    return (a+=b)>=mod?a-mod:a;
}
il int mul(int a,int b){
    return (LL)a*b%mod;
}

co int N=500000+10;
namespace T{
    int l[N<<2],r[N<<2];
    int tag[N<<2][2],sum[N<<2][2];
    int pro[N<<2];
    #define lc (x<<1)
    #define rc (x<<1|1)
    void build(int x,int l,int r){
        T::l[x]=l,T::r[x]=r;
        tag[x][0]=tag[x][1]=sum[x][0]=sum[x][1]=0;
        pro[x]=0;
        if(l==r) return;
        int mid=(l+r)>>1;
        build(lc,l,mid),build(rc,mid+1,r);
    }
    void set(int x,int k,int v){
        tag[x][k]=v,sum[x][k]=mul(r[x]-l[x]+1,v);
        pro[x]=mul(sum[x][k^1],v);
    }
    void push_down(int x){
        for(int k=0;k<2;++k)if(tag[x][k]){
            set(lc,k,tag[x][k]),set(rc,k,tag[x][k]);
            tag[x][k]=0;
        }
    }
    void push_up(int x){
        for(int k=0;k<2;++k)
            sum[x][k]=add(sum[lc][k],sum[rc][k]);
        pro[x]=add(pro[lc],pro[rc]);
    }
    void change(int x,int ql,int qr,int k,int v){
        if(ql<=l[x]&&r[x]<=qr)
            return set(x,k,v);
        push_down(x);
        int mid=(l[x]+r[x])>>1;
        if(ql<=mid) change(lc,ql,qr,k,v);
        if(qr>mid) change(rc,ql,qr,k,v);
        push_up(x);
    }
    int query(int x,int ql,int qr){
        if(ql<=l[x]&&r[x]<=qr)
            return pro[x];
        push_down(x);
        int mid=(l[x]+r[x])>>1;
        if(qr<=mid) return query(lc,ql,qr);
        if(ql>mid) return query(rc,ql,qr);
        return add(query(lc,ql,qr),query(rc,ql,qr));
    }
}
int n,a[N];
int s1[N],t1,s2[N],t2; // max,min

int main(){
    freopen("dance.in","r",stdin),freopen("dance.out","w",stdout);
    read(n);
    for(int i=1;i<=n;++i) read(a[i]);
    int ans=0;
    T::build(1,1,n);
    for(int i=1;i<=n;++i){
        while(t1&&a[s1[t1]]<=a[i]) --t1;
        T::change(1,t1?s1[t1]+1:1,i,1,a[i]);
        s1[++t1]=i;
        while(t2&&a[s2[t2]]>=a[i]) --t2;
        T::change(1,t2?s2[t2]+1:1,i,0,a[i]);
        s2[++t2]=i;
        ans=add(ans,mul(i,T::query(1,1,i)));
    }
    T::build(1,1,n),t1=t2=0;
    for(int i=n;i>=1;--i){
        while(t1&&a[s1[t1]]<=a[i]) --t1;
        T::change(1,i,t1?s1[t1]-1:n,1,a[i]);
        s1[++t1]=i;
        while(t2&&a[s2[t2]]>=a[i]) --t2;
        T::change(1,i,t2?s2[t2]-1:n,0,a[i]);
        s2[++t2]=i;
        ans=add(ans,mod-mul(i-1,T::query(1,i,n)));
    }
    printf("%d\n",ans);
    return 0;
}

数列

[問題の説明]
我々は、以下の特性を有する列の数であるN-列の数を定義します。

  1. 列の数の長さが3以上であり、かつ各要素の列の数は、nは1の整数です。
  2. 場合など番号12、...、M、その後、任意の3 <= kに対して<= M、満足
    K -a K-2 )(K-を1つの -aのK-2)<0

あなたは、N-列の数を求めているの数をn個を与えています。剰余十億七への答え。

[入力形式
seq.in.と呼ばれるファイルには、
入力コモンラインは、n個です。

[]出力形式の
出力ファイル名seq.out。出力ラインは、列の数を示しN-

試料1 [O]
seq.in
。3
seq.out
2

試料1 [O]は説明
二つの配列は、N-(2,1,3)及び(2,3,1)であります

サンプル2 [O]
seq.in
666
seq.out
805 846 404

[データサイズと表記]
データの10%は、N <= 10
データの30%に、N <= 200
N <=は、データの50%、2000年
のデータ70%、N <= 10 18である
100%データ,. 3 <= N <10 = 5000

問題やChiTongZに対する解決策

注目仮定\(A_ B_iは= {I} 1 -a_i + \) 次いで(\ | | B_i)を\単調増加され、そして\(B_i \)を交互に正と負。

検討- (a_iをiは\)\画像、折れ線グラフに接続し、その後、我々がしなければならないことを決定することである\を(a_iを\)変動幅、即ち、{| b_i \(\最大\ | | \} = | b_m \)し、この変動幅の解の数を見つけ、この範囲を配置するプログラムの数を乗じています。

列挙考えてみましょう(\ | | B_M)\を想定し、(b_mの\)\最後のいくつかのプログラムを乗じ、ポジティブである(2 \)\ことができます。
\ [\ Fracの12 ANS = \
sum_ {i = 1} ^ {N-1} 2 ^ {I-1}(N-1-I + 1)\] ので\(B \)厳密な性質、そう\(1 \は、SIM I-1 \) のいずれかの方法はスキームを出現するユニークです。

しかし、保証されていない(| \ {A_N \} | \ GE 3 \)\は、すなわち\(| \ {B_N \} | \ GE 2 \)は、そう減算する\(| \ {B_N \} | = 1 \)の状況。
\ [\ Fracの12 ANS = \ sum_ {i = 1} ^ {N-1} 2 ^ {I-1}(N-1-I + 1) - \ sum_ {i = 1} ^ {N-1} (N-1-I + 1 )\]

次いで、従来のルーチンにより算出され、回答
\ [ANS = 2 ^ {N + 1} -N ^ 2-N-2 \]

時間複雑\(O(\ N-LG)\)

#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
    T x=0,w=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*w;
}
template<class T> T read(T&x){
    return x=read<T>();
}
using namespace std;
typedef long long LL;

co int mod=1000000000+7;
il int fpow(int a,int b){
    int ans=1;
    for(;b;b>>=1,a=(LL)a*a%mod)
        if(b&1) ans=(LL)ans*a%mod;
    return ans;
}

int main(){
    freopen("seq.in","r",stdin),freopen("seq.out","w",stdout);
    int m=0,n=0;
    for(char c=getchar();isdigit(c);c=getchar()){
        m=((LL)m*10+c-'0')%(mod-1);
        n=((LL)n*10+c-'0')%mod;
    }
    int ans=fpow(2,m+1)+mod-((LL)n*n+n+2)%mod;
    printf("%d\n",ans%mod);
    return 0;
}

おすすめ

転載: www.cnblogs.com/autoint/p/test20190814.html