結果

問題 No.335 門松宝くじ
ユーザー startcppstartcpp
提出日時 2016-01-16 00:32:45
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 468 ms / 2,000 ms
コード長 2,898 bytes
コンパイル時間 780 ms
コンパイル使用メモリ 65,380 KB
実行使用メモリ 4,348 KB
最終ジャッジ日時 2023-10-19 23:51:33
合計ジャッジ時間 4,416 ms
ジャッジサーバーID
(参考情報)
judge12 / judge14
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,348 KB
testcase_01 AC 1 ms
4,348 KB
testcase_02 AC 2 ms
4,348 KB
testcase_03 AC 2 ms
4,348 KB
testcase_04 AC 2 ms
4,348 KB
testcase_05 AC 121 ms
4,348 KB
testcase_06 AC 180 ms
4,348 KB
testcase_07 AC 312 ms
4,348 KB
testcase_08 AC 214 ms
4,348 KB
testcase_09 AC 468 ms
4,348 KB
testcase_10 AC 467 ms
4,348 KB
testcase_11 AC 465 ms
4,348 KB
testcase_12 AC 464 ms
4,348 KB
testcase_13 AC 464 ms
4,348 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

//怒涛のタイプミス
#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;
}
0