原题链接:
http://codeforces.com/contest/496/problem/D
题意:比赛,数字1和2分别代表a,b获胜,规则是:①优先获得t次胜利的人,总分+1,当前小局得分清零②优先总分达到s的人获得总胜利,游戏结束。
思路:
①枚举t的值,然后依次判断谁优先获得t分,计算出a,b总分。
②总分大的人,与将游戏结束的人若相同,则t可行。
③枚举t的时候,用二分方法计算。
小优化:
①t枚举的范围,上限可优化为最终胜利人的总胜利局数。
②枚举t计算总分时,若计算到某t局胜利结束后,后面a和b胜利的局数都小于t了,则停止计算。
注意:
注意输出的顺序。需要重新排序一下。
#include "iostream"
#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;
int a[100010],b[100010],h=0,nans=-1,n,winer,sa=0,sb=0;
struct f
{
int s;
int t;
}ans[100010];
bool cmp(struct f a1,struct f a2)
{
if(a1.s!=a2.s)
return (a1.s<a2.s);
else
return (a1.t<a2.t);
}
void get_s(int i)
{
h=0;
sa=0;
sb=0;
while(a[n]-a[h]>=i||b[n]-b[h]>=i)
{
int l=h+1,r=n,m;
int tha=n+1,thb=n+1;
while(l<=r)
{
m=(l+r)/2;
if(a[m]-a[h]>=i)
{
tha=m;
r=m-1;
}
else
l=m+1;
}
l=h+1;
r=n;
while(l<=r)
{
m=(l+r)/2;
if(b[m]-b[h]>=i)
{
thb=m;
r=m-1;
}
else
l=m+1;
}
if(thb>tha)
{
h=tha;
sa++;
}
else
{
h=thb;
sb++;
}
}
if(h!=n)
sb=sa;
}
int main()
{
int num,nwin,w;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&num);
if(num==1)
{
a[i]=a[i-1]+1;
b[i]=b[i-1];
}
else
{
a[i]=a[i-1];
b[i]=b[i-1]+1;
}
}
if(a[n]!=a[n-1])
{
winer=1;
nwin=a[n];
}
else
{
winer=2;
nwin=b[n];
}
for(int i=1;i<=nwin;i++)
{
get_s(i);
if(winer==1&&sa>sb)
{
ans[++nans].s=sa;
ans[nans].t=i;
}
else if(winer==2&&sb>sa)
{
ans[++nans].s=sb;
ans[nans].t=i;
}
}
printf("%d\n",nans+1);
sort(ans,ans+nans+1,cmp);
if(nans>=0)
{
for(int i=0;i<=nans;i++)
printf("%d %d\n",ans[i].s,ans[i].t);
}
return 0;
}