結果
| 問題 |
No.335 門松宝くじ
|
| コンテスト | |
| ユーザー |
startcpp
|
| 提出日時 | 2016-01-16 00:32:45 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
AC
|
| 実行時間 | 431 ms / 2,000 ms |
| コード長 | 2,898 bytes |
| コンパイル時間 | 667 ms |
| コンパイル使用メモリ | 65,496 KB |
| 実行使用メモリ | 6,944 KB |
| 最終ジャッジ日時 | 2024-09-19 19:44:50 |
| 合計ジャッジ時間 | 3,921 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 10 |
ソースコード
//怒涛のタイプミス
#include <iostream>
#include <algorithm>
using namespace std;
int n, m;
int a[3][800]; //同じ行の要素の値は重複しない(Nの順列になっている)
const int depth = 10;
class Segtree{
public:
int data[2048];
Segtree(){ for( int i = 0; i < 2048; i++ ) data[i] = -1; }
void push(int pos, int val){
pos = (1 << depth) + pos - 1;
data[pos] = max(data[pos], val);
while( pos > 0 ){
pos = (pos - 1) / 2;
data[pos] = max(data[pos * 2 + 1], data[pos * 2 + 2]);
}
}
//今[a, b)を持つ葉にいる。[l, r)のmaxを計算する
int getMax(int l, int r, int a = 0, int b = (1 << depth), int pos = 0){
if( l >= r )
return -1;
if( l <= a && b <= r )
return data[pos];
if( r <= a || l >= b )
return -1;
int u = getMax(l, r, a, a + (b - a) / 2, pos * 2 + 1);
int v = getMax(l, r, a + (b - a) / 2, b, pos * 2 + 2);
return max(u, v);
}
};
class Segtree2{
public:
int data[2048];
Segtree2(){ for( int i = 0; i < 2048; i++ ) data[i] = 10000; }
void push(int pos, int val){
pos = (1 << depth) + pos - 1;
data[pos] = max(data[pos], val);
while( pos > 0 ){
pos = (pos - 1) / 2;
data[pos] = min(data[pos * 2 + 1], data[pos * 2 + 2]);
}
}
//今[a, b)を持つ葉にいる。[l, r)のminを計算する
int getMin(int l, int r, int a = 0, int b = (1 << depth), int pos = 0){
if( l >= r )
return 10000;
if( l <= a && b <= r )
return data[pos];
if( r <= a || l >= b )
return 10000;
int u = getMin(l, r, a, a + (b - a) / 2, pos * 2 + 1);
int v = getMin(l, r, a + (b - a) / 2, b, pos * 2 + 2);
return min(u, v);
}
};
double solve(int h){
Segtree seg;
Segtree2 seg2;
int i, j;
int pos[801];
double ans = 0;
for( i = 0; i < n; i++ ){
seg.push(i, a[h][i]);
seg2.push(i, a[h][i]);
pos[a[h][i]] = i;
}
int k;
for( i = 1; i <= n; i++ ){
for( j = i + 1; j <= n; j++ ){
//i < j < k(jが端っこ)
if( pos[i] < pos[j] ){
k = seg.getMax(0, pos[j]);
} else {
k = seg.getMax(pos[j] + 1, n);
}
if( j < k )
ans += k;
//i < k < j(kが端っこ)
int maxi = seg.getMax(0, min(pos[i], pos[j]));
int mini = seg2.getMin(0, min(pos[i], pos[j]));
int maxi2 = seg.getMax(min(pos[i], pos[j]) + 1, n);
int mini2 = seg2.getMin(min(pos[i], pos[j]) + 1, n);
if( (maxi > i || mini < j) || (maxi2 > i || maxi < j) )
ans += j;
//k < i < j(iが端っこ)
if( pos[j] < pos[i] ){
k = seg2.getMin(0, pos[i]);
} else {
k = seg2.getMin(pos[i] + 1, n);
}
if( k < i )
ans += j;
}
}
ans /= n * (n - 1);
ans *= 2;
return ans;
}
signed main()
{
cin >> n >> m;
for( int i = 0; i < m; i++ )
for( int j = 0; j < n; j++ )
cin >> a[i][j];
double e = -1;
int ans = -1;
for( int i = 0; i < m; i++ ){
double res = solve(i);
if( e < res ){
e = res;
ans = i;
}
}
cout << ans << endl;
return 0;
}
startcpp