AOJ0540 Amidakuji

問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0540

Read on →
Feb 10th, 2016

AOJ0534 Chain

問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0534

Read on →
Feb 9th, 2016

AOJ0535 Crossing Black Ice

問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0535

Read on →
Feb 9th, 2016
aoj, dfs

最近解いた問題

最近,AOJのVolume5を解いてる.解法をまとめないとすぐに忘れるのでメモ

Read on →

Year End's Hack Day 2015参加記

明治大学NCC主催 Year End’s Hack Day 2015に参加しました
http://eventdots.jp/event/576488

Read on →
Dec 20th, 2015

Codeforces335-div2D Lazy Student

グラフの頂点数,辺の数, 最小全域木を構築する辺とそれ以外の辺が与えられる.そのようなグラフが存在すればその一例を,そうでない場合は-1を出力する.

考察

最小全域木を構築する辺をコストの小さい順に一本につなげる.Sample 1では次のようにする.

後は最小全域木を壊さないように辺を追加する.2つの辺を選び,その端を結ぶことを考えるとその選び方は2乗通りある.

しかし,最小全域木を壊さないということは,選んだ2つの辺のコストよりも大きい辺を追加すれば良いので,小さい順に見ていけばよい.一本の線にする時に小さい順にしているので,前から見ていくことで,追加する辺の個数回で済む.

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <map>
#include <set>

#define REP(i,k,n) for(int i=k;i<n;i++)
#define rep(i,n) for(int i=0;i<n;i++)
#define INF 1<<30
#define pb push_back
#define mp make_pair

using namespace std;
typedef long long ll;
typedef pair<int,int> P;

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

  vector<pair<pair<int,int>, int> > v;
  rep(i, m) {
      int a, b;
      cin >> a >> b;
      v.push_back(mp(mp(a, b), i));
  }

  sort(v.begin(), v.end());

  vector<int> e;
  vector<P> q;
  vector<pair<int,pair<int,int> > > ans;
  int t = 0;
  rep(i, m) {
      int cost = v[i].first.first;
      int f = v[i].first.second;
      int j = v[i].second;

      if(f == 1) {
          e.push_back(cost);
          ans.push_back(mp(j, mp(t, t+1)));
          t++;
      }
      else if(f == 0) {
          q.push_back(mp(cost, j));
      }
  }

  bool flag = true;
  int from = 0, to = 1;
  for(int i = 0; i < q.size(); i++) {
      if(to == e.size()) {
          flag = false;
          break;
      }

      if(e[from] <= q[i].first && e[to] <= q[i].first) {
          ans.push_back(mp(q[i].second, mp(from, to+1) ));
      } else {
          P p = q.back();
          if(e[from] <= p.first && e[to] <= p.first) {
              ans.push_back(mp(p.second, mp(from, to+1)));
              q.pop_back();
          }
          i--;
      }

      if(from == to - 1) {
          from = 0;
          to++;
      } else {
          from++;
      }
  }

  if(flag) {
      sort(ans.begin(), ans.end());
      rep(i, ans.size()) {
          cout << ans[i].second.first+1 << " " << ans[i].second.second+1 << endl;
      }
  } else {
      cout << -1 << endl;
  }

  return 0;
}

選んだ辺のコストを超えないようにするということは,まず1つの辺を選んだ時に,それより小さい辺を見なければいけなかったが,大きい方の辺をずらしていくという意味の分からないことをしていてWAを連発した.

Dec 15th, 2015

Codeforces334-div2C Alternative Thinking

長さの'0'と'1'で構成された文字列が与えられる.ある区間を1度だけ反転して'0'と'1'が交互となる列の長さを最大化する.

考察

まず,文字列の交互列の長さをとすると,一度の反転で最大2しか増えないことが分かる.例えば,

のように出来る.また,の時以外に,区間を反転して長さが増えないケースを考えると,そのようなケースは無いと分かる.反転する区間で01を内包している場合,反転後をその部分は10で交互列になるからである.

よって,を超えないように,+1,+2したらACが貰えた

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <map>
#include <set>

#define REP(i,k,n) for(int i=k;i<n;i++)
#define rep(i,n) for(int i=0;i<n;i++)
#define INF 1<<30
#define pb push_back
#define mp make_pair

using namespace std;
typedef long long ll;
typedef pair<int,int> P;

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

  string s;
  cin >> s;

  int cnt = 0;
  bool flag = true;

  if(s[0] == '1') cnt++;

  rep(i, n) {
      if(flag) {
          if(s[i] == '1') continue;
          else {
              cnt++;
              flag = false;
          }
      } else {
          if(s[i] == '1') {
              cnt++;
              flag = true;
          } else continue;
      }
  }

  if(cnt + 2 <= n) cout << cnt + 2 << endl;
  else if(cnt + 1 <= n) cout << cnt + 1 << endl;
  else cout << cnt << endl;

  return 0;
}
Dec 15th, 2015

ProjectEuler 349 Langton's Ant

https://projecteuler.net/problem=349

行動回数をとしてとりあえずシュミレーションしてみる.

結果だけ見ても良くわからないので,動きを見てみた.

もっと大きな数をやった

!!!!!!!
めっちゃびっくりした.直線になるらしい
周期的になるだろうと思い10000から100ずつぐらいずらして数えた差を取ってみた

どうやら10000から始めると26で一周期になっているようだ.実際に2600ずつずらしてみた.

後はpythonで計算した.

1
2
3
4
720 + (10 ** 18 - 10000) / 2600 * 300
=> 115384615384614720
(10 ** 18 - 10000) % 2600
=> 2000

後は100ずつずらした時の20番目までを足した

submitしたら合ってた.良かった.

シュミレーションするコード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <map>
#include <set>

#define REP(i,k,n) for(int i=k;i<n;i++)
#define rep(i,n) for(int i=0;i<n;i++)
#define INF 1<<30
#define pb push_back
#define mp make_pair

using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int dy[4] = {-1, 0, 1, 0};
int dx[4] = { 0, 1, 0, -1};

vector< int > v[5005][5005];
const int GETA = 1000;
int N = 0;

void dfs(int y, int x, int dir, int c) {
  if(c == N) return;

  int n = v[y][x].size();
  v[y][x].push_back(c);

  int ndir = 0;
  if(n % 2 == 0) {
      ndir = (dir + 1) % 4;
  } else {
      ndir = (dir + 3) % 4;
  }

  int ny = y + dy[ndir];
  int nx = x + dx[ndir];

  dfs(ny, nx, ndir, c+1);
  return;
}

void print(int x) {
  REP(i, GETA-x, GETA+x+1) {
      REP(j, GETA-x, GETA+x+1) {
          cout << v[i][j].size() << " ";
      }
      cout << endl;
  }
}

void print2(int x) {
  REP(i, GETA-x, GETA+x+1) {
      REP(j, GETA-x, GETA+x+1) {
          if(v[i][j].size() % 2 == 0) {
              cout << " ";
          } else {
              cout << "O";
          }
      }
      cout << endl;
  }
}

int main() {
  vector<int> t;
  rep(k, 10) {
      N = k * 100 + 10000;
      rep(i, 2005) rep(j, 2005) v[i][j].clear();
      dfs(GETA, GETA, 0, 0);
  
      ll cnt = 0;
      rep(i, 5005) {
          rep(j, 5005) {
              if(v[i][j].size() % 2 == 1) {
                  cnt++;
              }
          }
      }
  
      t.push_back(cnt);
      cout << cnt << endl;
  }
  
  rep(i, t.size()-1) {
      cout << t[i+1] - t[i] << " ";
  }
  cout << endl;

  return 0;
}
Dec 5th, 2015

Codeforces332-div2C Day at the Beach

数列 h があり,hをソートした状態にしたい.区間に分けるとその区間ではソートすることが出来る.この分ける区間の数を最大化したい.

考察

数列hをソートし,ソート前とソート後で比較する.左から見て個数をカウントしていき,それが0に担った所を区切る.この区切り方は,数列hの区間をソートした数列が,ソートした数列hと一緒になる一番短い区間になる方法である.よってこれを繰り返すことで最大値が求まる.

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <map>
#include <set>

#define REP(i,k,n) for(int i=k;i<n;i++)
#define rep(i,n) for(int i=0;i<n;i++)
#define INF 1<<30
#define pb push_back
#define mp make_pair

using namespace std;
typedef long long ll;
typedef pair<int,int> P;

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

  vector<int> v(n), t(n);
  rep(i, n) {
      cin >> v[i];
      t[i] = v[i];
  }

  sort(t.begin(), t.end());
  int ans = 0;
  map<int, int> m;

  rep(i, n) {
      if(m[v[i]] == -1) {
          m.erase(v[i]);
      } else {
          m[v[i]]++;
      }

      if(m[t[i]] == 1) {
          m.erase(t[i]);
      } else {
          m[t[i]]--;
      }

      if(m.size() == 0) {
          ans++;
      }
  }

  cout << ans << endl;

  return 0;
}

本番中はよくわからないコードを書いていた.終了後にソートしたものと比較すれば良いことに気付いた...

Nov 25th, 2015

Codefestival 2015 参加記

適当に箇条書き.日本語がだいぶ怪しい

予選突破練習会

  • Codefes2014の予選AのD予選BのDに取り組む
  • RMQ解がバグる.stack解なるほどな〜となった.
  • ピザ美味い

予選A

既に書いていた

予選突破練習会2

  • ARC043BとCodefes2014の決勝Eに取り組む
  • その場でAC取れてワイワイ
  • ピザ美味い
  • お話を聞きながら,高田馬場まで歩くのむっちゃ楽しかったです

予選B

  • 優先度を順番にしてずらしていけば部分点(35点)が取れることに気づく.3完+部分点を達成
  • 131位で何とか通過出来た
  • 通過出来たのは,予選突破練習会のおかげです!!!

1日目

  • @teight_meightさんと待ち合わせして行こうと決める
  • 出会えず
  • 結構な時間迷って何とか会場にたどり着く
  • 45分遅れてスタート

A

サイズを見る - AC
http://code-festival-2015-final.contest.atcoder.jp/submissions/561950

B

真ん中でしょ,とか思って出す - AC
http://code-festival-2015-final.contest.atcoder.jp/submissions/562371

C

01と10を数えれば大丈夫でしょ,とか思って出す - AC
http://code-festival-2015-final.contest.atcoder.jp/submissions/562682

D

3回RMQすれば良いと気づく. - 6WAを生やす
通らないケースが1つだけなので,特殊なケースで落ちてると思いきや適当なテストケースを作って合わないことがわかる.直す - AC
http://code-festival-2015-final.contest.atcoder.jp/submissions/564347

E

パーカーが見えてきた. , -, !, -!, !!, -!!の6パターンに場合分け出来そう.0と非0をシュミレーションして場合分けする - AC
http://code-festival-2015-final.contest.atcoder.jp/submissions/565281

  • 157位でパーカー郵送組.ワイワイした
  • トークライブ,体が1つでは足りないと感じた
  • エキシビションマッチ,席の近くのモニター(yosupotさん)をずっと見ていた.雲の上の人のような,めちゃ強の人たちのコーディングが見れるのは非常に良いと思った

ホテル着

  • さて君を飲みに誘う
  • 7人ぐらいでぶっちぎり酒場へ
  • 酔っぱらい太郎
  • さて君の川柳を見ながらベッドで横になる

2日目

あさプロ.Easyに参加した.

A

以下をより小さいにしていて2WAを生やす
http://code-festival-2015-morning-easy.contest.atcoder.jp/submissions/569089

B

半分に分けて見る - AC
http://code-festival-2015-morning-easy.contest.atcoder.jp/submissions/569250

C

目標の点から引けば良いと考える. - WA
最初に0加えたり,色々直す - AC
http://code-festival-2015-morning-easy.contest.atcoder.jp/submissions/569518

D

半分に分けてlcsを取れば良いと気づく - AC
http://code-festival-2015-morning-easy.contest.atcoder.jp/submissions/570044

  • 28位でスタンプ貰う.ワイワイした
  • Mid Cを考えるけど解けず

リレー

  • Cを担当するも円周率 3.14しか言えず
  • 冷や汗ダラダラ思考停止
  • チームの方に円周率を教えてもらい何とかAC
  • グラフの数え上げをする.余り役に立たず
  • 難しい問題を解いてるチームの方を応援する.全く役に立たず
  • チームの方はいい人ばかりだった

まとめ

Codefestival2015最高でした
運営・参加者の方々お疲れ様でした,ありがとうございました.

Nov 21st, 2015