洛谷 P1199 三国游戏 题解

CSDN同步

原题链接

简要题意:

每两个武将都有一定的默契值。你和电脑轮流选择武将,电脑总会选择让你得不到最大默契值的那个武将;你要选择一种方法,使得你的最大默契值最大。如果会输给电脑则输出 \(0\),否则输出 \(1\) 和那个最大的默契值。

首先,人肯定比电脑聪明

如果你抱着骗分的态度

printf("0\n");

然后你会得到一个完美的 \(0pt\).

也就是说,始终存在某种方案,使得人可以胜利!

你会发现,电脑的选法是有些死板(但也有些道理)的,它总是会阻止你拿到最高的那个默契值。

所以,每行最大的默契值肯定不是你的。但也不是它的。为什么呢?

假设第 \(i\) 个武将和第 \(j\) 个武将拥有最高的默契值 \(k\).

此时如果你选了 \(i\)\(j\) 中的一个,那么电脑会选另一个,\(k\) 就谁也不属于。

如果你一个也不选,电脑肯定也不会来选这两个,所以 \(k\) 仍然谁也不属于。

那么结论得到了,既然最大值抢不到,可不可以抢次大值?

比方说,\(i\) 号武将和 \(j\) 号武将仍有最高的默契值 \(k\),而 \(i\) 号武将和另一个 \(x\) 号武将有次大的默契值 \(y\).

此时你选了 \(i\),然后电脑把 \(j\) 拿走了,紧接着你再拿走 \(x\).

此时,在与 \(i\) 号武将的所有搭配中,你占了优势:因为最大值谁也没捞到,但你却捞到了次大值。

类似的,每一行的最大值都是谁也没捞到,但你却捞到了每一行的次大值。

首先你显然胜利了,其次,那么你搭配的最大值是多少呢?

显然,就是 每一行的次大值的最大值

/yiw

意思是,把每行的次大值搞出来,再这 \(n\) 个数中取最大值!

吐槽:数据太弱了。(爆搜都能拿 \(70pts\),这什么东西)

你可能觉得,把每一行开 \(\texttt{vector}\) 分别排序即可,取次大值打擂即可。

时间复杂度: \(O(n^2 \log n)\).

还真过了?

好,那加强一下。

对于 \(100 \%\) 的数据,\(N \leq 5 \times 10^3\).

你会发现,此时你要用 \(O(n)\) 的时间取出次大值。

你打擂法没学好吧,这还叫加强,我真是服了

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

const int N=5e2+1;

inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
	int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}

int n,a[N][N];
int ans=0;

int main(){
	n=read();
	for(int i=1;i<n;i++)
	for(int j=1;j<=n-i;j++) {
		a[i][j+i]=read();
		a[j+i][i]=a[i][j+i];
	} for(int i=1;i<=n;i++) {
		int max1=0,max2=0; //max1 是最大值,max2 是次大值
		for(int j=1;j<=n;j++)
			if(a[i][j]>max1) max2=max1,max1=a[i][j]; //此时两个值一起变
			else if(a[i][j]>max2) max2=a[i][j];      //只改变次大值
		ans=max(ans,max2);	
	} printf("1\n%d\n",ans);
	return 0;
}

posted @ 2020-03-22 16:53  bifanwen  阅读(189)  评论(0编辑  收藏  举报