Codeforcesラウンド#608(本部2)問題への解決策

Codeforcesラウンド#608(本部2)問題への解決策

序文

トピックリンク:ただ、キーワードとして話題の便宜のために私の問題だけ(エスケープへの解決策を見つけることができるようにします

Codeforces 1271A

Codeforces 1271B

Codeforcesの1271C

Codeforces 1271D

Codeforces 1271E

重要:問題に対するFのソリューションがあり、我々は行くことができる不死の問題にFの問題の解決策を見てみたいです

A.スーツ

問題の意味

あなたは\(\)ネクタイ、\(B \)スカーフ、\(C \)ベスト、\(D \)ジャケット、二つのパッケージがあります。

  • 過ごしネクタイ、ジャケット、\(E \)

  • スカーフ、ベスト、ジャケット、費やした\(F \)

どのくらいのお金は、(別途販売されていない)まで販売して取得することができます。(暴利)

練習

我々が得る質問の意味によると:

存在する場合(I \)\\(E \)要素セットが、それは価格である(iは\回E +分\ \ {ジ、B、C \} \ \ F回) 要素、(列挙することができますそのノート\(I \) \(DI \) \(B \) \(C \)は負に現れることはできません)。

プログラム

#include<bits/stdc++.h>
using namespace std;

int a,b,c,d,e,f,ans;

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>a>>b>>c>>d>>e>>f;
    for(int i=0;i<=min(a,d);i++){//数据范围小,直接暴力枚举
        ans=max(ans,i*e+min((d-i),min(b,c))*f);
    }
    cout<<ans<<endl;

    return 0;
}

B.ブロック

FST私は本当にあまりにも料理でした

問題の意味

あなたの行を与える\(N \)四角、黒または白の各四角で、各操作の色は、2つの隣接する正方形を逆にすることができ、そしてかどうかを尋ねた(3N \)\全体への転化の数で行が同じ色です。

練習

現在のブロックが白ではなく、それはその背後にあるブロックを反転し、finallyブロックがOKに白であれば操作は、完了している仕上げされた場合、再びバックにフロントを実行し、シーケンスが白に反転していると仮定します。同様に黒、現在のブロックがそれを逆にするブラックボックスでない場合、再びフロントバックの実行に、シーケンスは黒に反転されると仮定し、その背後に、そして最終的に操作がOKに黒で終了した場合は、このボックスを終了します。最後に、あなたが出力できない場合は、\(--1 \)

プログラム

#include<bits/stdc++.h>
using namespace std;

int n;
char s[205];
vector<int> op;

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>n;
    cin>>s+1;
    //假设全是白色:
    for(int i=1;i<n;i++){
        if(s[i]=='B'){
            s[i]='W';
            s[i+1]=s[i+1]=='W'?'B':'W';
            op.push_back(i);
        }
    }
    //判断最后一个方块:
    if(s[n]=='W'){
        cout<<op.size()<<endl;
        for(int i=0;i<op.size();i++){
            cout<<op[i]<<' ';
        }
        cout<<endl;
        return 0;
    }
    //假设全是黑色:(此时可以直接再操作同一个序列)
    for(int i=1;i<n;i++){
        if(s[i]=='W'){
            s[i]='B';
            s[i+1]=s[i+1]=='W'?'B':'W';
            op.push_back(i);
        }
    }
    //判断最后一个方块
    if(s[n]=='B'){
        cout<<op.size()<<endl;
        for(int i=0;i<op.size();i++){
            cout<<op[i]<<' ';
        }
        cout<<endl;
        return 0;
    }
    cout<<-1<<endl;

    return 0;
}

C. Shawarmaテント

Bよりも簡単

問題の意味

あなたは、デカルト座標系の平面を与えます(ちょうどええ数学を学びました)学校の後とあなたを与える(N \)\学校から生徒の家庭ならば、全体の学校からのポイントの異なるでShawarmaを購入するテントを構築するためにあなたを求めて、魔法を学生座標(全体のポイントです)パスは購入する後(消費者があなたをだますとき)、あなたはいくつかの学生まで購入することが求められますし、10トンのこの時間は、座標(あなたがいずれかの座標できます)(暴利)

注:全体のポイントは、横軸を指し、縦軸ポイントは整数です。マジックパスだけ上昇させる二つの(横方向または縦方向に平行)との間のダウン最短パス(長さが2点間のマンハッタン距離である)(二点間の複数のバーが存在してもよいです)。

練習

明らかに、より近い学校、その上にどの最高の見ている限り、学校の列挙として4ポイント程度上下を通じて10トンからより多くの学生が存在します。

プログラム

#include<bits/stdc++.h>
using namespace std;

int n,sx,sy;
int x[200005],y[200005];
int l,r,u,d;
//l, r, u, d 分别表示左右上下的帐篷经过的学生个数

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>n>>sx>>sy;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        if(x[i]>sx)r++;
        if(x[i]<sx)l++;
        if(y[i]>sy)u++;
        if(y[i]<sy)d++;
        //对于经过帐篷的学生计数
    }
    if(r>=l&&r>=r&&r>=u&&r>=d){
        cout<<r<<endl;
        cout<<sx+1<<' '<<sy<<endl;
    }else
    if(l>=l&&l>=r&&l>=u&&l>=d){
        cout<<l<<endl;
        cout<<sx-1<<' '<<sy<<endl;
    }else
    if(u>=l&&u>=r&&u>=u&&u>=d){
        cout<<u<<endl;
        cout<<sx<<' '<<sy+1<<endl;
    }else
    if(d>=l&&d>=r&&d>=u&&d>=d){
        cout<<d<<endl;
        cout<<sx<<' '<<sy-1<<endl;
    }
    //这里的u>=u之类只是方便copy&paste罢了

    return 0;
}

D.ポータル

問題は、実際に翻訳したくない、長いああに直面します

問題の意味

あなたは取る必要があります\(N \)の都市。初めに、あなたが持っている\(K \)の兵士を。最初のテイク\(I \)の都市を、あなたに必要な\(a_iを\)兵士(攻撃中に兵士を失うことなく)、あなたのキャプチャ後にキャッチします(b_i \)\あなたが取る、あなたのチームを拡大するために二人の若い男性の後守るために兵士を送ることができる、防衛はあなたのスコアの増加になります\(C_I \) 兵士の損失を。2つの方法で防御:

  • あなたの場所に守ることができます\(I \)の都市

  • そこ\(M \)片道ポータルから\(U \)(V \)\、もしあなた\(U \) あなたが守るために軍隊を送ることができます\(V \)直接ポータルでなければなりません接続されている都市)

あなたが最初から持っている(1 \)\座席が最初にキャプチャしてきました\(N \)の都市、あなたはすべての都市を捉えることができない場合、あなたは失われている、出力は\( - 1 \) 勝った場合、最大スコアを見つけます。

練習

貪欲計算ない(req_i =最大\ {A_ \ {I + 1}、{req_ I + 1} - B_ {I + 1} \} | req_n = 0 \)は、 セクションを表し\(I \)都市克服し、そこに\(b_i \)兵士が参加した後、あなたはゲームは兵士の最小値を必要と完了します。、空いた兵士の一部が存在します後\(I \)都市の新しい兵士の数を空と呼ばれる(fr_i \)\うまく、その後、大根ヒープでの発送の兵士への都市に。

この場合は、\(I \)都市はその最後の街を守ることができますと呼ばれる(def_i \)\から、(1 \)\(私は\)\アイドル兵士のは、明らかに(アイドル兵士を、それを守ることができますあなたは)次の街にあなたに従うことができます。

プログラム

#include<bits/stdc++.h>
using namespace std;

int n,m,k;
int a[5005],b[5005],c[5005],fr[5005];
vector<int> g[5005];//无用数组
int def[5005],req[5005];
priority_queue<pair<int,int> > pq;
int ans;

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>n>>m>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i]>>b[i]>>c[i];
        def[i]=i;
    }
    for(int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);//无用语句
        def[v]=max(def[v],u);
    }
    for(int i=n;i>=1;i--){
        req[i]=max(a[i+1],req[i+1]-b[i+1]);cerr<<i<<' '<<req[i]<<endl;
    }
    //计算req[i]
    int cur=k;
    for(int i=1;i<=n;i++){
        if(cur<a[i]){
            cout<<-1<<endl;
            return 0;
        }
        cur+=b[i];
    }
    //↑判断是否能赢↑
    cur=k;
    for(int i=1;i<=n;i++){
        cur+=b[i];
        fr[i]=cur-req[i];cur=req[i];
        pq.push(make_pair(c[i],i));
    }
    //计算fr[i],初始化以重量为第一关键字降序排列的堆
    while(!pq.empty()){
        int val=pq.top().first,x=pq.top().second;
        pq.pop();
        int y=def[x];
        while(!fr[y]&&y>0)y--;
        if(y==0)continue;
        fr[y]--;//贪心地选择最后一个能选的城市的空闲士兵
        ans+=val;
    }
    cout<<ans<<endl;

    return 0;
}

E.共通番号

問題の意味

Eは、人々がそれを知っている必要がありません。私は書いていないし、顔は非常に簡単な質問(エスケープ

練習

定義された\(K_I \)であっ\(I \)パスの数。

まず、奇数と偶数、あなたは同じでしょう分けて考える\(\ N-を)同じことが、奇数であるかさえ、(Y- \)\大きなは\(k_y \)モノトーンので、することができ、確かに小さい二部。

私たちは、その記事が含まれているどのようにパスの数を計算するには、単一の番号を探します。

他の方法ラウンドの経路の計算は、逆推力パスで描画することができる、唯一のもプラスであるが、すべての数字は2で乗算することができます。どのように多くのレコードは、このようにその上に番号を取得することができます。我々はより高速な方法を必要とするので、しかし、これは、遅すぎます。

最小値から上、同じによって結果、2回観察することにより(2つだけ乗算)までの最大値に(それぞれが2つのプラスワンを有する乗算した後に)、との間のすべての数値が達成可能であり、限り、我々は最小と最大の複雑さを計算するために好きなように - 。確かに2プラスよりも速く成長していることであるので、2を乗じた1種類のそれぞれの回数は、この間隔の長さは、パスの数は、それに追加されています。

プログラム

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

ll n,k;

bool check(ll m){
    ll l=m,r=m,res=0;
    if(!(m&1)){r++;}//当m是偶数时给r增加1
    for(int i=1;;i++){//其实i没有什么用
        res+=min(n,r)-l+1;//添加区间长度到返回值
        //for(int j=l;j<=min(r,n);j++)cerr<<j<<' ';
        l<<=1;
        r=(r<<1)+1;//计算下一个l和r
        if(l>n)break;//当l大于n时就没有计算的必要了,直接退出
        
    }//cerr<<endl;
    return res>=k;
}

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>n>>k;
    //for(int i=1;i<=n;i++)check(i);
    ll l=1,r=(n+1)/2,m,ans;//二分奇数
    while(l<=r){
        m=(l+r)>>1;
        if(check(2*m-1)){
            ans=2*m-1;
            l=m+1;
        }else{
            r=m-1;
        }
    }
    l=1;r=n/2;//二分偶数
    while(l<=r){
        m=(l+r)>>1;
        if(check(2*m)){
            ans=max(ans,2*m);//由于ans已经取了奇数的值,所以这里是max
            l=m+1;
        }else{
            r=m-1;
        }
    }
    cout<<ans<<endl;

    return 0;
}

結論

ポイントにおけるITアウト!

申し訳ありませんが、私は人々の質問Fにない助けることができない、(エスケープ私はそう

おすすめ

転載: www.cnblogs.com/BlahDuckling747/p/Codeforces-Round-608-Div-2-Ti-Jie.html