ちゃっくのメモ帳

ちゃっくがメモしときたいことをメモしとくよ

Codeforces #418 Div2 C An impassioned circulation of affection

コンテスト中に解けなかったやつ...

Problem - C - Codeforces

概要

文字列sが与えられる.(sの長さ\leq1500)
クエリがq個飛んでくる(q\leq200000)
各クエリはm(1\leq m \leq n)と文字cが与えられる.
文字列sの文字のうちm個をcに書き換えた場合,部分文字列でcのみからなるも文字列の最長の長さを求めよ

解法

1.各文字cに対してs[0..i]に含まれるcの個数の累積和を求める.
2.累積和を用いて各文字cに対して,「長さi」のcからなる部分文字列を作るのに書き換える必要のある文字の数を求める
3.各クエリに対して「書き換える必要のある文字の数がm以下になっている最大の長さ」を(2)で求めた結果から計算する

計算量はO(|s|q)でギリギリかな

コード

int n;
string s;
int q;
int m;
char c;

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

    vector<vector<int>> cnt(26);
    for(char c='a';c<='z';c++){
        int i = c-'a';
        cnt[i] = vector<int>(n+10,0);
        for(int j=0;j<n;j++){
            if(s[j]==c) cnt[i][j+1] = cnt[i][j]+1;
            else cnt[i][j+1] = cnt[i][j];
        }
    }

    vector<vector<int>> need(26,vector<int>(n+10,0));
    for(char c='a';c<='z';c++){ //26
        for(int i=1;i<=n;i++){  //1500
            int mn = 0;
            for(int j=0;j<n;j++){
                int s = j;
                int t = s + i;
                if(t>n) break;
                // s[s..t)
                int num = cnt[c-'a'][t] - cnt[c-'a'][s];
                mn = max(mn,num);
            }
            need[c-'a'][i] = i-mn;
        }
    }

    rep(loop,q){
        cin >> m >> c;
        int ans = 0;
        for(int i=0;i<=n;i++){
            if(need[c-'a'][i] <= m) ans = i;
        }
        cout << ans << endl;
    }
}

感想

qの値が微妙だから計算量から方法思いつきにくい気がしたけど前計算が必要なことは分かりそうなのでこのくらいは解きたかった...

あと問題文に化物語が使われてるけど西尾維新の作品て外国人が読んでも楽しいのかな...?同音異義語で遊ぶような作品だから言語が変わるとその面白さはなくなりそうだよね.

ABC060D Simple Knapsack解いたんだよ

dp解

 dp[i][j] := i個使用して重さの総和が j+w_0 iとなるときの価値の最大値
とする.
ここで重さを直接持つと配列に収まらないのでw_iの代わりに w_i - w_0を使用することで配列に収まるようにできる

注意点

内部のループは逆に回さないと同じ荷物を何度も使用できてしまうので注意

コード

ll N,W;
ll w[128],v[128];
ll dp[128][512];
 
int main(){
    cin >> N >> W;
    rep(i,N) cin>>w[i]>>v[i];
 
    ll sum=0;
    rep(i,N){
        ll ww = w[i]-w[0];
        // 荷物iを複数回使わないように逆に回す
        for(int j=i;j>=0;j--){  // 荷物iを含まないでj個
            for(int k=sum;k>=0;k--){    // 荷物iを含まない時の重さがk
                dp[j+1][k+ww] = max(dp[j+1][k+ww],dp[j][k]+v[i]);
            }
        }
        sum += ww;
    }
 
    ll ans=0;
    for(int i=0;i<=N;i++){
        for(int j=0;j<=sum;j++){
            if(w[0]*i+j>W) continue;
            ans = max(ans,dp[i][j]);
        }
    }
    cout << ans << endl;
}

感想

想定解を最初に思いついたがdp解で通してるひとが結構いたのでやってみた
想定解のほうが思いつきやすいと思うけどナップサックだからdpのほうがイメージしやすいのかなぁ

C++のmapの最大のキーをとる

C++のstd::mapのキーで最小のキーはbegin()を使用し,最大のキーはrbegin()を使用すればよい.

間違えて最大のキーを取得する際にend()を使ってしまったのでメモ.
endは最終要素の次にアクセスしてしまうので値が不定になる(多分).
未定義動作になるらしいです
map::end - C++ Reference
実際に" It does not point to any element, and thus shall not be dereferenced."とある.

#include <iostream>
#include <map>

int main(){
    std::map<int,int> mp = {
        {2,20},
        {5,50},
        {4,40},
    };

    int minv = mp.begin()->first;
    int maxv = mp.rbegin()->first;
    std::cout << minv << std::endl; // 2
    std::cout << maxv << std::endl; // 5

    int e = mp.end()->first;
    std::cout << e << std::endl;    // 3 (最後の要素の次を指してるので何が入ってるか不明)

}

修正

上の赤字で示した部分修正受けました.ありがとうございます
ピーー☆━━━━━…‥‥(・_・ヽ) アリガタビーム!!

RUPCに参加してきました

RUPC2017に参加してきたので参加記を...

~前日~
前日まで大学の友人と旅行をしていたので昼神温泉から中津川まで車に乗せていってもらい、中津川からはrian,葦くんとともに名古屋→京都に行く.
京都でちょっと観光してからホテルに向かおうということで伏見稲荷大社を訪れて山登りしたが僕の体力が底をついて途中リタイア


京都駅で夕食を探して歩き回るも何も見つからずラーメン街へ
その後瀬田駅まで行ってホテルへGO.

~1日目~


余裕を持って?到着。立命館大学では卒業式をやっていたらしく大量に人がいた.
--コンテスト--
コンテストではらてさんと葦くんと同じチーム(Achalatte)になり、僕はまずAを担当したがRE.どうもAOJはC++でreutrn 0をしないとREになるらしく再提出→WA.バグらせた。なんか実装ミスってたので葦くんにコーディング譲ってその後にAC.次にEを担当し、DPだとはわかるが状態の持ち方が悪くてTLEしそうなのでらてさんにアドバイスもらって書く.最期見る所を間違えてサンプルとおらないがらてさんに教えてもらってAC.気がついたら葦くんがCをACしてた.
あとはらてさんが無双して全完.すごかった...

解説聞いたらAで無駄なことしまくってて泣いた.

~2日目~
---コンテスト---
rianと葦くんと「1回はこの三人ででたいよね」という話をしていたのでこの3人で組んだ.トイレから帰ってきたらチーム名がtaitekku_000で決まってて笑った.
最初A,B,Cをぱぱっと通していこうということでrianがAをサクッと通せば良くない?(結論)みたいな会話が行われrianがAを通す.僕はBを担当したが問題名が「GPAじゃんけん」で2週間後くらいにほんとにGPAじゃんけんすることを思い出して泣く(どうでもいい).Bを通した後にD,Eを読むが無理そうなので葦くんに渡してFをやる.Fは「壁が4つあって実装めんどいな...」って言ってたらりあんに「右下と左上だけでよくない」と言われてコーディング開始.最初dfsで書いてたらバグったのでbfsにしたらxとnxを間違えたり,bfsで訪れたところのチェックミスったりしてTLEやWAを連発しまくるもりあんデバッグしてもらいながらAC.こういうミスをやめたい...
Fでコーディング時間を無限に奪ってしまったのが申し訳なかった...

---懇親会---


~3日目~
---コンテスト---
rian,葦と出てもよかったがせっかくなのでチーム決めに参加した.kawabysさんとRIKAさんとチームckrででた.
とりあえずRICAさんA,僕B,kawabysさんCで...ということになったが問題読んで僕とRICAさんがA,Bを交換.気がついたらkawabysさんがC問題を通しててプロかった.そして僕はAを書くがWAしてkawabysさんに手伝ってもらいながらデバッグするも通らないのでkawabysさんに投げる.D,Eがダイクストラとセグ木かなって話になりセグ木を書き始めるが計算量的に無理だと気が付きkawabysさんに相談すると遅延セグ木と言われたがそんなものは知らないのでDを書き始める.拡張ダイクストラは書き慣れていたのですんなりかけてAC(オーバーフローしたくせにすんなりとは...).RIKAさんがBをとおしてkawabysさんがAをとおして終わり.
Aを投げてしまったのが本当に申し訳なかった...


---帰路---
帰るときに京都によって昼飯を食べることに...四条に行ってみたが「ビジネス街やん!」ってなってぶらぶらしながら昼飯を探し適当にラーメン屋に行ってみる.濃口醤油というのが美味しかった.
京都駅に戻って「抹茶スイーツを食べないと...」という使命感にかられるもどこも人が多くて新幹線の時間に間に合わなさそう....なので諦めかけたら西尾の店に入って抹茶パフェを食べることができた...よかった...


~~~~~~
RUPCとても楽しかったです!運営の方々ありがとうございました!

BCU30に参加したっぽい?

3/11にBattle Conference U30にプロコン枠で参加しました.
(行くぞ~)
浜松町から思ったよりも遠くてお昼ごはんの時間がなくなった...
のでコンビニを探したがなかなか見つけられなくて日の出駅?の近くでローソン?を見つけてお昼ごはんを買う.


(会場到着)
なんか14:00までに入場かと思ってたら13:30らしいという噂もあって遅刻かとおもったけど入れた...

今回のプロコンは3人1チームで2時間で6問を解くことになりチームはmkiken氏,HORI氏とのチームになりました.
とりあえず問題を割り振り、なんか適当に順番に振り分ければいいかってなり
mkikenさん: A,D
僕 : B,E
HORIさん : C,F
と担当し分からなければお互いに教え合うことにしました.

(コンテスト開始)
とりあえず開始したらmkikenさんがAを通し次に僕がBのコーディングするがコピペしたあとにインデックス直しわすれて3WAだしてしまった....

ここでHORI氏がCに詰まっているのでmkikenさんがDをコーディングして通す.僕はEを考えるがO(N^2K^2)の解法しか思い浮かばない...
のでこれを提出してみると2ケースがTLEになるだけなので定数倍高速化で通せるのでは?と判断し高速化を始める.

一旦コーディングを交代してHORI氏がC問題を実装+AC.

Fはどうしようもないと判断しE問題を高速化(cin,coutをやめたりinline関数にしたり...).. 5回くらいTLEした後に残り5分でAC.

(コンテスト終了)
(解説)
どうもEはやはりO(N^2K^2)は想定解でなかったらしい。C++が好きになった.

(起業ブースめぐり)
色々な起業から色々頂く.個人的にサイボウズさんのサイボウズキャンディーが面白かった.
あとabemaTVのシール!abemaTVでアニメ見まくってるので嬉しい

(懇親会)
なんかあちこちから🍣がすごいとの噂を聞いていたらすごかった.マグロの頭が置いてあった...
あとホットドック食べた.ソーセージ2本刺したらなんか嬉しくなった.

(帰宅)
家に帰ったら誰もいなくて鍵も持ってないのでカラオケにいった.楽しかった


(___)
プロコンしてたのでバトルトークみれなかったのが残念だった...
いくつか見たかったのあった...

tmux-256colorを入れる

tmuxでdefault-terminalをtmux-256colorにしたかった.

しかしなんかubuntu16.04でtmux-256colorが入ってなかった.

https://github.com/tmux/tmux/blob/master/FAQ#L366-L373

これを試した見たけれど失敗....

ここでaptでncurses-termを入れてみたら/usr/share/terminfo/t/tmux-256colorができた!

Xmas Contestに参加したっぽい?

クリスマスイブ!
とくに予定もないのでXmas contestに参加しました。このコンテストはチームでの参加が許されていたので、すごぷろさんにチームを組んで頂いて参加しました。(開始4分前に突然チームを組もうとお願いする馬鹿の図?)

部室に集まって解くことにしました。

とりあえずA問題.
僕「とりあえずできるだけ大きい2の累乗を取っていったらどうですかね!」
とこのまま実装して56点を取る。流石に56点じゃ悲しいので考察を続けて「N/2を超える最大の2の累乗の数を左と右からとっていって被った部分を引く」という解法を考え,最初の1回だけに適用する。これで75点。ここまで順調だったので「毎回これにすればいいんじゃない!」とか調子に乗る。実装して提出してみると27点。絶望。改善を入れても33点程度。ならば2の累乗の数2個 or 3個に分割できるときだけ別で分ければ良いのじゃないかと考えたりしてみる。

ここですごぷろさんがBを出して24点獲得してEを時始めてた。

この時点で自分らより上にA100点が結構いたのでAをもう少し頑張るが、いい方法が思い浮かばなくて困る(;´・ω・)。
諦めてI問題にうつる。

I問題を読んでたらすごぷろさんがEで100点をだす。凄い。。。そのまますごプロさんはJ問題を始めた。

とりあえずIの部分点を狙うが実装が面倒臭そうなのと計算量が厳しそうなのですごぷろさんに相談。計算量についてはすごぷろさんと部分点なら行けるのではと考え実装し始める。

実装つらい。

ここで僕が実装をバグらせる && 実装をそもそも間違える
をしてしまい計算量が凄く大きくなって(多分予定の10^4倍くらい大きくなった...)しまうが残り数秒なので諦め。

すごぷろさんは知らない間にJを50点とってた。。。。
終了。


昼の部21位で結構良い順位じゃないかとおもったけどどう考えても僕の功績殆ど無いですよね!!!すごぷろさんチーム組んでくれてありがとうございました!

その後部室で考察したりおしゃべりしたりでぐだぐだ~して帰りました(o_o)v