結果
問題 | No.335 門松宝くじ |
ユーザー | kopricky |
提出日時 | 2017-10-13 07:49:02 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 121 ms / 2,000 ms |
コード長 | 11,102 bytes |
コンパイル時間 | 2,459 ms |
コンパイル使用メモリ | 193,176 KB |
実行使用メモリ | 5,248 KB |
最終ジャッジ日時 | 2024-11-17 11:16:59 |
合計ジャッジ時間 | 3,457 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 2 ms
5,248 KB |
testcase_04 | AC | 1 ms
5,248 KB |
testcase_05 | AC | 16 ms
5,248 KB |
testcase_06 | AC | 23 ms
5,248 KB |
testcase_07 | AC | 37 ms
5,248 KB |
testcase_08 | AC | 121 ms
5,248 KB |
testcase_09 | AC | 61 ms
5,248 KB |
testcase_10 | AC | 59 ms
5,248 KB |
testcase_11 | AC | 55 ms
5,248 KB |
testcase_12 | AC | 58 ms
5,248 KB |
testcase_13 | AC | 54 ms
5,248 KB |
コンパイルメッセージ
main.cpp: In member function ‘void RMQ::make_cartesian_tree()’: main.cpp:98:26: warning: ‘buff’ may be used uninitialized in this function [-Wmaybe-uninitialized] 98 | tree[buff].par = i; | ^
ソースコード
#include <bits/stdc++.h> #define ll long long #define INF 1000000005 #define MOD 1000000007 #define EPS 1e-10 #define rep(i,n) for(int i=0;i<(int)n;++i) #define each(a,b) for(auto (a): (b)) #define all(v) (v).begin(),(v).end() #define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end()) #define fi first #define se second #define pb push_back #define show(x) cout<<#x<<" = "<<(x)<<endl #define spair(p) cout<<#p<<": "<<p.fi<<" "<<p.se<<endl #define svec(v) cout<<#v<<":";rep(kbrni,v.size())cout<<" "<<v[kbrni];cout<<endl #define sset(s) cout<<#s<<":";each(kbrni,s)cout<<" "<<kbrni;cout<<endl #define smap(m) cout<<#m<<":";each(kbrni,m)cout<<" {"<<kbrni.first<<":"<<kbrni.second<<"}";cout<<endl using namespace std; typedef pair<int,int>P; const int MAX_N = 805; class node { public: int id, val; int par, left, right; }; class RMQ { public: vector<node> tree; vector<int> arr; vector<int> euler_tour, depth, diff, visit_id; int node_size, root, arr_len, kind; vector<int> Block_arr, diff_bit; //各ブロックで深さが最小になるようなインデックス 各ブロックのdiffの情報をビットに詰めたもの vector<vector<int> > Sparse_Table; //i番目から長さ2^kの区間に含まれるdepthのうち最小のインデックス vector<vector<vector<int> > > Table_Lookup; int block_size, block_rem, block_cnt, log_block_cnt; void make_cartesian_tree(); void make_euler_tour(int cur_node, int& id, int cur_depth); void make_Block_arr(); void make_Sparse_Table(); void make_diff_bit(); void make_Table_Lookup(); P PM_RMQ(int st, int ed); int rmq(int st, int ed); RMQ(vector<int>& arg1, int arg2=0){ //arg3=1のときrange_max_queryを表す node_size = (int)arg1.size(); arr.resize(node_size, 0); if(arg2){ for(int i = 0; i < node_size; i++){ arr[i] = -arg1[i]; } }else{ for(int i = 0; i < node_size; i++){ arr[i] = arg1[i]; } } kind = arg2; make_cartesian_tree(); euler_tour.resize(2 * node_size - 1, -1), depth.resize(2 * node_size - 1, -1); diff.resize(2 * node_size - 2, -1), visit_id.resize(node_size, -1); int val = 0; make_euler_tour(root, val, 0); for(int i = 0;i < 2 * node_size - 2; i++){ diff[i] = depth[i+1] - depth[i]; } //±RMQの実装 arr_len = 2 * node_size - 1; make_Block_arr(); make_Sparse_Table(); make_diff_bit(); make_Table_Lookup(); } }; void RMQ::make_cartesian_tree() { tree.resize(node_size); for(int i = 0; i < node_size; i++){ tree[i] = (node){i, arr[i], -1, -1, -1}; } stack<P> st; //インデックス,値 st.push(make_pair(0,arr[0])); root = 0; for(int i = 1; i < node_size ; i++){ int buff; while(1){ //iが根となる場合 if(st.empty()){ st.push(make_pair(i, arr[i])); tree[i].left = buff; tree[buff].par = i; root = i; break; } pair<int, int> top = st.top(); if(top.second <= arr[i]){ tree[i].par = top.first; //iの親を変更 int nd = tree[top.first].right; //iの親の右下のノード //iの子となるものが存在する場合 if(nd != -1){ tree[i].left = nd; //iの親の右下のノードをiの左の子とする tree[nd].par = i; //iの親の右下のノードの親をiとする } tree[top.first].right = i; //iの親の右下の子をiとする st.push(make_pair(i,arr[i])); break; } buff = top.first; //最後にpopされたものを暗記 st.pop(); } } } void RMQ::make_euler_tour(int cur_node, int& id, int cur_depth) { visit_id[cur_node] = id; euler_tour[id] = cur_node; depth[id++] = cur_depth; if(tree[cur_node].left >= 0){ make_euler_tour(tree[cur_node].left, id, cur_depth+1); euler_tour[id] = cur_node; depth[id++] = cur_depth; } if(tree[cur_node].right >= 0){ make_euler_tour(tree[cur_node].right, id, cur_depth+1); euler_tour[id] = cur_node; depth[id++] = cur_depth; } } void RMQ::make_Block_arr() { block_size = ceil(log2(arr_len)/2); block_cnt = (arr_len - 1) / block_size + 1; block_rem = arr_len % block_size; log_block_cnt = ceil(log2(block_cnt)) + 1; Block_arr.resize(block_cnt); for(int i = 0; i < block_cnt; i++){ int mn = INT_MAX; int mn_id = -1; for(int j = 0; j < block_size; j++){ int now_id = i * block_size + j; if(now_id >= arr_len){ break; } if(depth[now_id] < mn){ mn = depth[now_id]; mn_id = now_id; } } Block_arr[i] = mn_id; } } void RMQ::make_Sparse_Table() { Sparse_Table.resize(block_cnt, vector<int>(log_block_cnt, -1)); for(int i = 0; i < block_cnt; i++){ Sparse_Table[i][0] = Block_arr[i]; } for(int j = 0; j < log_block_cnt - 1; j++){ for(int i = 0; i < block_cnt; i++){ if(i + (1 << j) >= block_cnt){ Sparse_Table[i][j + 1] = Sparse_Table[i][j]; }else{ if(depth[Sparse_Table[i][j]] <= depth[Sparse_Table[i + (1 << j)][j]]){ Sparse_Table[i][j + 1] = Sparse_Table[i][j]; }else{ Sparse_Table[i][j + 1] = Sparse_Table[i + (1 << j)][j]; } } } } } void RMQ::make_diff_bit() { diff_bit.resize(block_cnt, -1); for(int i = 0; i < block_cnt; i++){ int num = 0; for(int j = 0; j < block_size - 1; j++){ int now_id = i * block_size + j; if(now_id >= arr_len){ break; } if(diff[now_id] > 0){ num += (1 << (block_size - j - 2)); } } diff_bit[i] = num; } } void RMQ::make_Table_Lookup() { Table_Lookup.resize((1 << block_size), vector<vector<int> >(block_size + 1, vector<int>(block_size + 1, 0))); //0は減少,1は増加 for(int i = 0; i < (1 << block_size); i++){ vector<int> vec(block_size - 1, -1); for(int j = 0; j < block_size; j++){ if(i & (1 << (block_size - j - 2))){ vec[j] = 1; } } for(int j = 0; j < block_size; j++){ int nw = 0, mn = 0, mn_id = j; Table_Lookup[i][j][j+1] = j; for(int k = j + 2; k <= block_size; k++){ nw += vec[k-2]; if(nw < mn){ mn = nw; mn_id = k-1; } Table_Lookup[i][j][k] = mn_id; } } } } //インデックスと値のpair pair<int, int> RMQ::PM_RMQ(int st, int ed) { int st_block_id = (st == 0)?0:((st - 1) / block_size + 1); //ブロック区間の開始 int ed_block_id = ed / block_size - 1; //ブロック区間の終了 int st_id = st / block_size; int ed_id = ed / block_size; int st_rem = st % block_size; int ed_rem = ed % block_size; int st_val = Block_arr[st_id]; int ed_val = Block_arr[ed_id]; int res, mn = INT_MIN; if(ed_block_id - st_block_id < 0){ //間にブロック区間がひとつもない場合 if(st_id == ed_id){ //同じブロック区間に存在する場合 int id_kari = block_size * st_id + Table_Lookup[diff_bit[st_id]][st_rem][ed_rem + 1]; return make_pair(euler_tour[id_kari], arr[euler_tour[id_kari]]); }else{ int cand1 = block_size * st_id + Table_Lookup[diff_bit[st_id]][st_rem][block_size]; int cand2 = block_size * ed_id + Table_Lookup[diff_bit[ed_id]][0][ed_rem + 1]; if(depth[cand1] <= depth[cand2]){ return make_pair(euler_tour[cand1], arr[euler_tour[cand1]]); }else{ return make_pair(euler_tour[cand2], arr[euler_tour[cand2]]); } } }else{ //間にブロックっ区間が存在する場合 int num = floor(log2(ed_block_id - st_block_id + 1)); int cand1 = Sparse_Table[st_block_id][num]; int cand2 = Sparse_Table[ed_block_id-(1 << num) + 1][num]; int c1,c2; if(depth[cand1] <= depth[cand2]){ c1 = cand1; }else{ c1 = cand2; } int cand3 = block_size * st_id + Table_Lookup[diff_bit[st_id]][st_rem][block_size]; int cand4 = block_size * ed_id + Table_Lookup[diff_bit[ed_id]][0][ed_rem + 1]; if(depth[cand3] <= depth[cand4]){ c2 = cand3; }else{ c2 = cand4; } if(depth[c1] <= depth[c2]){ return make_pair(euler_tour[c1], arr[euler_tour[c1]]); }else{ return make_pair(euler_tour[c2], arr[euler_tour[c2]]); } } } //範囲は[st,ed) int RMQ::rmq(int st, int ed) { if(st == ed){ if(kind){ return -INF; }else{ return INF; } } pair<int, int> res = PM_RMQ(min(visit_id[st], visit_id[ed-1]), max(visit_id[st], visit_id[ed-1])); if(kind){ return -res.second; }else{ return res.second; } } int pos[3][MAX_N]; int mn[3][MAX_N][MAX_N]; int mx[3][MAX_N][MAX_N]; int main() { cin.tie(0); ios::sync_with_stdio(false); int n,m; cin >> n >> m; vector<vector<int> > val(m,vector<int>(n)); rep(i,m){ rep(j,n){ cin >> val[i][j]; pos[i][val[i][j]] = j; } } vector<RMQ> mn,mx; rep(i,m){ mn.pb(RMQ(val[i],0)),mx.pb(RMQ(val[i],1)); } double ans = 0; int id = 0; rep(i,m){ double res = 0; for(int j=1;j<n;j++){ for(int k=j+1;k<=n;k++){ int cand = 0; if(pos[i][j] < pos[i][k]){ int res = mx[i].rmq(0,pos[i][k]); if(res > k){ cand = res; }else if(mx[i].rmq(0,pos[i][j]) > j || mn[i].rmq(pos[i][j]+1,pos[i][k]) < j || mn[i].rmq(pos[i][k]+1,n) < k){ cand = k; } }else{ int res = mx[i].rmq(pos[i][k]+1,n); if(res > k){ cand = res; }else if(mn[i].rmq(0,pos[i][k]) < k || mn[i].rmq(pos[i][k]+1,pos[i][j]) < j || mx[i].rmq(pos[i][j]+1,n) > j){ cand = k; } } res += 2.0*cand/(n*(n-1)); } } if(ans + EPS < res){ ans = res; id = i; } } cout << id << endl; return 0; }