0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ABC393個人的備忘録

Posted at

存在しないものを追い求めた男の備忘録です

コンテスト概要

AtCoder Beginner Contest 393

開催日:2025年2月15日 21:00-22:40

A - Poisonous Oyster

考察

やろうと思えばスマートな解法も出来そうだが、どうせ4パターンしかないので全部書く。
食べた牡蠣を勘違いしていないかだけ注意。

提出

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

int main(){
    string x,y;
    cin >> x >> y;

    if(x == "fine" && y == "fine") cout << "4" << endl;
    if(x == "fine" && y == "sick") cout << "3" << endl;
    if(x == "sick" && y == "fine") cout << "2" << endl;
    if(x == "sick" && y == "sick") cout << "1" << endl; 
}

B - A..B..C

考察

どうせ制約が100なので三重ループを回す。

制約がデカければBを固定してACを探したりすれば何とかなるかな?

提出

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

int main(){
    string s;
    cin >> s;

    int len = s.length();

    int ans  = 0;
    for(int i=0;i<len;i++){
        if(s[i] != 'A') continue;
        for(int j=i+1;j<len;j++){
            if(s[j] != 'B')continue;
            for(int k=j+1;k<len;k++){
                if(s[k] != 'C')continue;

                //差が同じならカウント
                if(j-i == k-j)ans++;
            }
        }
    }

    cout << ans << endl;    
}

C - Make it Simple

考察

専門用語(?)が並んでややこしそうだが、要するに

〇同じ頂点を指している
〇同じペアがすでに結ばれてる

このような辺だけを順に撤去すればよい。

提出

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

int main(){
    int n,m;
    cin >> n >> m;

    //頂点同士が結ばれているかを確認する用
    map<pair<int,int>,bool>mp;
    int ans  = 0;
    for(int i=0;i<m;i++){
        int x,y;
        cin >> x >> y;

        //調べやすいよう大小関係を整える。
        if(x > y) swap(x,y);
        
        if(x == y) ans++;//同じ頂点ならいらない
        else if(mp[{x,y}]) ans++;//すでに結ばれているならいらない
        else mp[{x,y}] = true;//そうでないなら辺を結ぶ
    } 

    cout << ans << endl;
}

D - Swap to Gather

考察

めんどくさそうなのでいったんEに行ったのが間違いだった。
まず集合させるべき「1」を決める。
この時、ある「1」と基準の「1」の間にある「0」の数が移動させる回数になる。
これをすべての「1」について行いトータルの回数を出す。
もちろん毎回数えるとTLEなので累積和をあらかじめ調べておく。

右からの累積和を間違えたせいで40分近く無駄にする羽目に。

提出

D.cpp
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main(){
    int n;
    string s;
    cin >> n >> s;

    vector<ll>op (0);//'1'と'1'の間の'0'の数をまとめる。
    ll cnt = 0;
    bool che = false;
    for(auto x:s){
        if(x == '1'){
            if(che){
               op.push_back(cnt);
            }else che = true;
            cnt = 0;
        }else cnt++;
    }    

    if(op.size() == 0){
        cout << "0" << endl;
        return 0;
    }

    ll k = op.size();
    ll sum = 0;
    for(auto x:op){
        sum += k*x;
        k--;
    }

    k = op.size();
    vector<ll>lf (k+1,sum);

    int a = k,b = 1;
    
    for(int i=1;i<k+1;i++){
        lf[i] = lf[i-1];
        lf[i] -= op[i-1] * a;
        a--;
    }

    sum = 0;
    for(int i=0;i<k;i++){
        sum += b * op[i];
        b++;
    }
    vector<ll>rg (k+1,sum);
    b=k;
    for(int i=k-1;i > -1;i--){
        rg[i] = rg[i+1];
        rg[i] -= op[i] * b;
        b--;
    }
    
    ll ans = (1LL<<60);
    for(int i=0;i<k+1;i++){
        ans = min(ans,lf[i] + rg[i]);
    }

    cout << ans <<endl;
}

E - GCD of Subset

考察

各数字ごとに約数を列挙しておいて、約数の登場回数をメモしておけばAの約数のうちK回以上登場しているものを出力すればOK。

なんだが、約数列挙が時間かかりすぎでTLE。高速に出来る方法はないかと模索するもうまくいかず。結局大幅な時間ロス。

完全なる取捨選択ミス。

結果

ABCD 4完 87:04

順位 4879位
パフォーマンス 709

感想

入水後1発目に茶パフォですか...
完全にやらかしてしまった。

とりあえず水パフォの問題をしっかりと復習しなければ...

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?