刚开始想用两侧循环来枚举S,T,请仔细一想没有必要,因为T确定了,S也就确定了
于是使用1层循环枚举T,这样我们看赢的多的人的局数,即为S
注意以下四种情况
1:没有人赢(无解)
2:两个人赢的一样多(无解)
3:赢的多的人却输了最后一局(因为先拿到大局数的人胜,显然最后一局是多的人赢的)
4:没有用完所有对局数大局就结束了(无解)
这样我们进行枚举,复杂度N^2,这是70的数据
其实我们不需要枚举,计算某个人谁先拿到T分(也就是赢下小局)时使用二分+前缀和的办法,看誰拿到T分的位置靠前(可以使用lower_bound实现,不会百度!)
复杂度:N*logN
可以AC
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
int sum1[199999],sum2[199999];
int cnt,n;
struct tw{
int s;
int t;
};
tw ans[99999];
inline void work(int t)
{
int s1=0;
int s2=0;
int s1_win=0;
int s2_win=0;
int last_win=0;
int w=0;
while(1)
{
int w1=lower_bound(sum1+w,sum1+n+1,s1+t)-sum1;
int w2=lower_bound(sum2+w,sum2+n+1,s2+t)-sum2;
if(w1>n&&w2>n) break;
if(w1<w2) s1_win++,last_win=1;
else s2_win++,last_win=2;
w=min(w1,w2);
s1=sum1[w];
if(w1>n) s1=1e7;
s2=sum2[w];
if(w2>n) s2=1e7;
}
if(w!=n) return;
if(s1_win==s2_win) return;
if(s1_win>s2_win&&last_win==2) return;
if(s1_win<s2_win&&last_win==1) return;
int win=max(s1_win,s2_win);
ans[++cnt].s=win,ans[cnt].t=t;
}
bool comp(const tw&a,const tw&b)
{
if(a.s<b.s) return 1;
if(a.s>b.s) return 0;
return a.t<b.t;
}
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
scanf("%d",&n);
for(int i=1,a;i<=n;i++)
{
scanf("%d",&a);
sum1[i]=sum1[i-1];
sum2[i]=sum2[i-1];
if(a==1) sum1[i]++;
else sum2[i]++;
}
for(int i=1;i<=n;i++)
work(i);
sort(ans+1,ans+cnt+1,comp);
if(!cnt) printf("0");
else
{
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)
printf("%d %d\n",ans[i].s,ans[i].t);
}
return 0;
}
重改后代码。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
int s,t;
}a[110000];
int cnt;
bool comp(node x,node y)
{
if(x.s==y.s) return x.t<y.t;
return x.s<y.s;
}
int n;
int cnt1[110000],cnt2[110000];
void check(int t)
{
int nows1=0,nows2=0,flag=0;
int last_win=0;
int nowwin1=t,nowwin2=t;
while(1)
{
int s1=lower_bound(cnt1+1,cnt1+n+1,nowwin1)-cnt1;
int s2=lower_bound(cnt2+1,cnt2+n+1,nowwin2)-cnt2;
if(s1>n&&s2>n) break;
if(s1<s2)
{
nows1++,last_win=1,nowwin1=cnt1[s1]+t,nowwin2=cnt2[s1]+t;
if(s1==n) flag=1;
}
else
{
nows2++,last_win=2,nowwin1=cnt1[s2]+t,nowwin2=cnt2[s2]+t;
if(s2==n) flag=1;
}
}
if(flag&&nows1>nows2&&last_win==1) a[++cnt]=((node){nows1,t});
if(flag&&nows1<nows2&&last_win==2) a[++cnt]=((node){nows2,t});
}
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
scanf("%d",&n);
for(int i=1,x;i<=n;i++)
{
scanf("%d",&x);
if(x==1)
cnt1[i]=cnt1[i-1]+1,cnt2[i]=cnt2[i-1];
else cnt1[i]=cnt1[i-1],cnt2[i]=cnt2[i-1]+1;
}
for(int i=1;i<=n;i++)
check(i);
sort(a+1,a+cnt+1,comp);
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)
printf("%d %d\n",a[i].s,a[i].t);
}