D. Tennis Game(思维,模拟实现)

好难啊…

策 略 很 明 显 , 枚 举 t , 计 算 此 时 的 s 策略很明显,枚举t,计算此时的s ,t,s

为了方便,令两个人分别叫做A和B

暴 力 计 算 需 要 O ( n 2 ) , 考 虑 如 何 加 速 暴力计算需要O(n^2),考虑如何加速 O(n2),

回想一下,我们在暴力的过程中有什么可以优化的

现在已知赢一局需要 t t t分,所以第一局分出胜负的位置

要么在A赢 t t t局的位置,要么在B赢 t t t局的位置

这两个位置谁比较小就是谁赢,设这个位置在 n o w now now

那 么 把 A 和 B 都 提 到 n o w 这 个 位 置 那么把A和B都提到now这个位置 ABnow

我 们 可 以 很 容 易 得 出 在 n o w 这 个 位 置 A 赢 了 x 局 , B 赢 了 y 局 我们可以很容易得出在now这个位置A赢了x局,B赢了y局 nowAx,By

类 似 的 , 可 以 知 道 下 一 次 分 出 胜 负 的 位 置 是 A 赢 x + t 局 , B 赢 y + t 局 位 置 的 较 小 值 类似的,可以知道下一次分出胜负的位置是A赢x+t局,B赢y+t局位置的较小值 ,Ax+t,By+t

所以预处理A和B赢k局的位置

预处理A和B在第k个回合赢了多少局

就可以一直跳跳跳检查,思维难度不小,实现难度更大

#include 
using namespace std;
const int maxn=2e5+10;
int f[maxn],g[maxn],n,top1,top2;
int a[maxn],b[maxn];
vector >ans;
int main()
{
	cin >> n;
	memset(f,127,sizeof(f));
	memset(g,127,sizeof(g));
	for(int i=1;i<=n;i++)
	{
		int x;
		cin >> x;
		if( x==1 )	f[++top1]=i;
		else	g[++top2]=i;
		a[i]=top1,b[i]=top2;
	}
	for(int t=1;t<=n;t++)
	{
		bool flag=1;
		int s1=0,s2=0,cur1=0,cur2=0;
		for(int cur=0;cur<=n;)//当前进行到第几局游戏 
		{
			if( cur1+t>top1&&cur2+t>top2 )//最后都不是在n点结束的 
			{
				flag=0;
				break;
			}
			int x=f[cur1+t],y=g[cur2+t];
			if( xy&&s1>s2 )	flag=0;//x赢最后一盘但是反而赢了
				if( s1==s2 )	flag=0;//平局 
				break; 
			}
			cur=now;
		}
		if( flag )	ans.push_back( make_pair(max(s1,s2),t) );
	}
	sort( ans.begin(),ans.end() );
	cout << ans.size() << endl;
	for(int i=0;i

你可能感兴趣的:(CF1900)