[説明] Codeforcesラウンド#600(Div.2)

Codeforcesラウンド#600(Div.2)

https://codeforces.com/contest/1253/problem

A.Singleプッシュ

アイデア:あなたは学士号を取得し、その後、減算配列。すべて0の場合、または唯一のいくつかの非ゼロと同じ図のためにそれ以外の場合は実行不可能、実現可能です。特定の実装では、最初の数の中間ポインタの双方が0ではないが見つかりました、そして、中間の同じ数であるか否かを判断することができます。複雑\(O(N)\)

注:複数のデータセットが必要に空にするかどうかを決定する必要があります。ここでI [N + 1]がクリアされていない、test55に結果WA ......

ACコード:

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+20;
int a[M];
int main(){
    int T;
    scanf("%d",&T);
    for (int z=1;z<=T;++z){
        int n;
        scanf("%d",&n);
        for (int i=1;i<=n;++i)
            scanf("%d",&a[i]);
        a[n+1]=0;
        int c;
        for (int i=1;i<=n;++i){
            scanf("%d",&c);
            a[i]-=c;
        }
        bool v=true;
        int l=1,r=n;
        while(l<=n&&a[l]==0)
            ++l;
        while(r>l&&a[r]==0)
            --r;
        int std=a[l];
        if (std>0)
            v=false;
        else
            for (int i=l;i<=r;++i)
                if (a[i]!=std){
                    v=false;
                    break;
                }
        if (v)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
} 

B.Silly間違い

アイデア:あなたは、人がオフィスに入ったかどうかを記録するためにunordered_mapと、オフィスの内部に現在あるunordered_setレコードを使用することができます。正の場合は、各イベントでは、それ以外の場合は1に、この男を記録し、違法であるあなたはそれを入力した場合、それは以前に、入力されたか否かを判断し、追加セットされ、それが負の場合、最初のセットであるかを決定、あれば違法ではない、そうでない場合は、この人を削除し、空にここに事務所かどうかを判断し、その後(その日が簡単に分けることができることを話題ため)一日の終わりとして直接空ならば、。複雑\(O(N)\)

注意:

  1. \(O(1)\)クリアSTL:同じに直接組み込まれ、各直接ST = ST0。
  2. 多くの場合は、(ログを削除)unordered_map unordered_setと複雑さを最適化するために使用されるが、立ち往生アウト(ハッシュ)注意することができます。しかし、私はおそらく(CF上)ニールさんのブログに詳細に説明するように、ランダム化されたハッシュを書くことを意味し、そのスタックアウトを確保するための方法を考えることはできません。

ACコード:

#include<bits/stdc++.h>
using namespace std;
const int M=2e6+20,P=1e6;
vector<int> vec;
unordered_set<int> st;
unordered_map<int,int> mp,mp0;
int c[M];
int main(){
    int n;
    scanf("%d",&n);
    bool v=true;
    for (int i=1;i<=n;++i)
        scanf("%d",&c[i]);
    for (int i=1;i<=n;++i){
        if (c[i]>0){
            if (mp[c[i]+P]){
                v=false;
                break;
            }
            else
                st.insert(c[i]),mp[c[i]+P]=1;
        }
        else{
            if (st.count(-c[i])){
                st.erase(-c[i]);
                if (st.empty())
                    vec.push_back(i),mp=mp0;
            }
            else{
                v=false;
                break;
            }
        }
    }
    if (!st.empty())
        v=false;
    if (!v)
        printf("-1\n");
    else{
        printf("%d\n%d",vec.size(),vec[0]);
        for(int i=1;i<vec.size();++i)
            printf(" %d",vec[i]-vec[i-1]);
    }
    return 0;
}

食べるC.Sweets

アイデア:まず、欲だけで、常に食べ考えるのは簡単です(a_iを\)\総最小ペナルティので、より多くの砂糖を。しかし、すべての場合において問題必要な出力はk = 1〜M。いくつかの例は、単に大に小さいから求めることができる後、次いで、kはそれぞれに1つずつインクリメントされ、答えがソート後に追加される\([K \%M ]、[K \%M + M]、[K \%M + 2M] ... \) インデックスkより大きくありません。そう長いシーケンスの最初の行として、各前処理後\(K \%M \)プレフィックス、再度、出力回答をスキャン。複雑\(O(nlogn)\)

注:オープンLLは父親が表示されません。

ACコード:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int M=2e5+20;
int a[M];
vector<LL> mmd[M]; 
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i)
        scanf("%d",&a[i]); 
    sort(a+1,a+n+1);
    for(int i=0;i<m;++i){
        int j=1;
        mmd[i].push_back(a[i]);
        while(j*m+i<=n)
            mmd[i].push_back(mmd[i][j-1]+a[j*m+i]),++j;
    }
    LL ans=a[1];
    printf("%lld",ans);
    for (int i=2;i<=n;++i){
        ans+=mmd[i%m][i/m];
        printf(" %lld",ans);
    }
    putchar('\n');
    return 0;
}

D.Harmoniousグラフ

思考: lの間、全ての点が通信でなければならないR、パスがある場合にLとR:この質問を見つけることができ、トピックの説明は、と等価です。その後、我々はに対処するためにばらばらのセット(DSU)を使用して考えることができます。

各片面〜第が組み合わされ、次いで各スキャンの後にセットにわたって調べるために、各レコードは、要素のCNT数、最小点及び最大点シリアル番号MNのMXを設定します。

MX-MN + 1 = cntが、その後、このコレクションの要素は、Mnであるとした場合、\(\ SIM \) MX、質問の意味は条件を満たすことができます。

MX-MN + 1 <cntが、その後、他のコレクションで説明している場合、我々は、彼らがポイントを逃しに入れることができます前に、いくつかのポイントをアップリンク2のセットを持っていると思います。[接続2セットはエッジのみ、プラスへの直接の答えを追加する必要があります。

もちろん、接続後の完成の大規模なコレクションはまだこの状態は、これまで満たされるまで、上記の手順を続けて、MX-MN + 1 = CNTを満たさない場合があります。すべての設定された条件が満たされたときは、出力答えをすることができます。

だから、どのように不足しているコレクションのポイントを見つけるには?私たちは、互いに素セットをそれぞれのMX、唯一のCNT MNを記録するために、小から大にMNに従い、すべて互いに素セット。条件のi番目のセットが満たされていない場合、それは確かにI + 1番目のMNポイントセットを失われます合併はこれまでのところ満足するまで継続して満足していない場合、それは、私と私の合併の+ 1セットとなります。これは、プライオリティキューで達成することができます。

複雑さは互いに素セットと優先キューがある\(O(nlogn)\) 一定のビットの大きなを達成するために、しかし、140msのを失っていました。

注:そこにあれば\(O(N + M) \) アプローチ......チュートリアルそれを振り返ります。

ACコード:

#include<bits/stdc++.h>
using namespace std;
const int M=2e5+20;
int road[M];
int fnd(int x){
    return (x==road[x])?x:road[x]=fnd(road[x]);
}
void merge(int u,int v){
    road[fnd(u)]=fnd(v);
}
struct Bcj{
    int mn,mx,cnt;
    Bcj(int a=1e9+7,int b=0,int c=0):mn(a),mx(b),cnt(c){}
    void proc(int i){
        mn=min(mn,i);
        mx=max(mx,i);
        ++cnt;
    }
    void clear(){
        mn=1e9+7;
        mx=cnt=0;
    }
    void merg(Bcj x){
        mn=min(mn,x.mn);
        mx=max(mx,x.mx);
        cnt+=x.cnt;
    }
}bcj[M];
struct cmp{
    bool operator()(Bcj x,Bcj y){
        return x.mn>y.mn;
    }
};
priority_queue<Bcj,vector<Bcj>,cmp> q;
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    int a,b;
    for (int i=1;i<=n;++i)
        road[i]=i;
    for (int i=1;i<=m;++i){
        scanf("%d%d",&a,&b);
        merge(a,b);
    }
    for(int i=1;i<=n;++i)
        bcj[i].mx=bcj[i].mn=i,bcj[i].cnt=1;
    for(int i=1;i<=n;++i)
        if (i!=fnd(i)&&bcj[i].mx)
            bcj[fnd(i)].proc(i),bcj[i].clear();
    //for(int i=1;i<=n;++i)
    //  cout<<bcj[i].mn<<' '<<bcj[i].mx<<bcj[i].cnt<<endl;
    for(int i=1;i<=n;++i)
        if (bcj[i].mx)
            /*cout<<bcj[i].mn<<' '<<bcj[i].mx<<' '<<bcj[i].cnt<<endl,*/q.push(bcj[i]);
    Bcj prs;
    int ans=0;
    while(!q.empty()){
        Bcj prs=q.top();
        q.pop();
        while(prs.cnt!=prs.mx-prs.mn+1){
            prs.merg(q.top());
            q.pop();
            ++ans;
        }
    }
    printf("%d\n",ans);
    return 0;
}

E.Antennaカバレッジ

問題の意味:ストリートMポイント[1、m]は、n個の送信局とは、各送信局は、2つのパラメータがあり、\(X_I \)\(S_Iが\)に位置する送信局表す\(X_Iを\) カバーできる\([X_I-S_I、S_I + S_I]を\) 我々は、各送信局1coin過ごすことができる(S_I \)\ [M、1] 1増加し、少なくとも完全に覆うことができるよう過ごすする方法多くのコイン尋ねました。2つの送信局が同じ場所にならないことを確認してください。\(1 \ n型のLeq \のLeq 80 \)、\ (N- \のLeq M \のLeq 100000 \)

アイデア:データの範囲を参照するには、時間のVPがdpを推測する必要がありますが、私はどのように転送思ったことはありません。実際に万一の図のように難しいことではありません。DP [i]を表し、Aカバー[1、i]が最小コストを提供し、次いで、2つの転送方法があります。

  1. 直接転送されたプログラムから[1、I-1]です。iが被覆されている場合は、[I] = DP [I-1] DP; iはで覆われていない場合は、I-1の基地局1の再膨張を覆い、そこDP [I] = DPせ[I-1] +1。
  2. 右のエンドポイントは、<= iが基地局から転送されます。そこDP [I] =分(DP [i]は、I-ANT [J] .R + DP [MAX(2 *アリ[j]は、ξ-1,0)])。前記アリ[j]は、j番目の基地局を示し、rは基地局を表し、(X - jがS_j + \)\このステップは、転送複雑であり、すべての適格な基地局を列挙することである(\ O(N))\

回答DP [M]は、[1、m]の間隔アレイは可視前処理事前に確立が必要かどうかを決定することによって覆われ、複雑さが最悪である(O(NM)\)\、DPは複雑である\(O(MN )\) 全体的な複雑さがあるので(O(NM)\)\

注意:

  1. 基地局(X = 0、S = 0)を追加します。任意のプログラムの範囲をカバーするために、この基地局と最悪なので、それは答えには影響しません(常に最小を取ります)。
  2. (注)前処理としないときは、クロスボーダーDPには最小値がゼロである左。

ACコード:

#include<bits/stdc++.h>
using namespace std;
const int M=1e5+20;
struct Ant{
    int x,s,l,r;
    Ant(int a=0,int b=0,int c=0,int d=0):x(a),s(b),l(c),r(d){}
    bool operator<(Ant x){
        return r<x.r;
    }
}ant[100];
int dp[M],vis[M];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i){
        int x,s;
        scanf("%d%d",&x,&s);
        ant[i]=Ant(x,s,x-s,x+s);
        for(int j=max(0,x-s);j<=min(m,x+s);++j)
            vis[j]=1;
    }
    dp[0]=0;
    for (int i=1;i<=m;++i){
        if (vis[i])
            dp[i]=dp[i-1];
        else
            dp[i]=dp[i-1]+1;
        for (int j=1;j<=n;++j)
            if (ant[j].r<=i)
                dp[i]=min(dp[i],i-ant[j].r+dp[max(2*ant[j].x-i-1,0)]);
    }
    printf("%d\n",dp[m]);
    return 0;
}

概要

今回はタイトルDはABCコードの実装と同じ程度の大物が、作ったが、それは昔の問題の前に書かれた、少し遅い書き込みと感じますが、ABC WAそれぞれの外に、コードを書くのスタイルや習慣を示すか、しないでくださいよく、Dのタイトルが速くしたい、自分を賞賛。Eは本当に問題があるべきアウトと思ったが、また書きたいしそうでしないでください。1800年に明日の夜に戦うCF。

おすすめ

転載: www.cnblogs.com/diorvh/p/11886557.html