好难啊…
为了方便,令两个人分别叫做A和B
回想一下,我们在暴力的过程中有什么可以优化的
现在已知赢一局需要 分,所以第一局分出胜负的位置
要么在A赢 局的位置,要么在B赢 局的位置
这两个位置谁比较小就是谁赢,设这个位置在
所以预处理A和B赢k局的位置
预处理A和B在第k个回合赢了多少局
就可以一直跳跳跳检查,思维难度不小,实现难度更大
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int f[maxn],g[maxn],n,top1,top2;
int a[maxn],b[maxn];
vector<pair<int,int> >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( x<y ) s1++; else s2++;
int now=min(x,y);//进行到第now局比赛了
cur1=a[now],cur2=b[now];//第now局比赛时,此时1赢了cur1盘,2赢了cur2盘
if( now==n )
{
if( x<y&&s1<s2) flag=0;//x赢最后一盘但是反而输了
if( x>y&&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<ans.size();i++)
printf("%d %d\n",ans[i].first,ans[i].second);
}