乒乓球

问题描述

GobMichael常在一起打乒乓球。他们是这样决定比赛的输赢的:比赛由若干大局组成;谁最先赢下s大局谁就获得比赛的胜利;在每一大局中,谁先得t分就获得本大局的胜利。

在一次比赛中,他们只记录了比赛中的每一分是谁得的,但忘记了记录st。现在给出比赛的每一分的得分情况,求出所有可能的stGob保证,得分表是完整的,也就是在比赛恰好在最后一人,得到最后一分后结束。

输入格式(game.in)

第一行一个整数N,代表比赛一共得到了多少分。

第二行N个整数,代表比赛中每一分是谁得到的;1代表Gob2代表Michael

输出格式(game.out)

第一行一个整数M,代表共有多少种可能的s,t情况。

接下来M行每行两个整数si, ti,代表一种可能的s,t情况。M种情况按照s从小到大输出;在s相等时按照t从小到大输出。

样例输入1

5

1 2 1 2 1

样例输出1

2

1 3

3 1

样例输入2

5

1 2 2 2 1

样例输出2

0

样例输入3

10

1 1 2 1 1 1 2 2 1 1

样例输出3

3

1 7

3 2

7 1

数据范围与约束

对于50%的数据,N<=1000

对于100%的数据,1<=N<=100,000

思路:

  一看就是一道搜索题,我也搜了,然而只拿了70分。原来还需要二分的。。。。

  (1)先枚举t,从1到n。

  (2)算一下两人最后的胜利局数,再结合最后一局是谁赢得来判断是否加到答案序列中。

  (3)在查找过程中,二分查找比较快

#include<iostream>
#include<queue>
#include<math.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,a[100009],ans,f1[100009],f2[100009];
struct node{
    int s,t;
}b[90000];
bool cmp(node A,node B)
{
    return A.s < B.s;
    return A.t < B.t;
}
void work(int x)
{    
    int np,nq,kp,kq,cp=0,cq=0,last,i;
    for( i=0;i<n;i)
    {
         np=f1[i]+x;
        nq=f2[i]+x;
        kp=lower_bound(f1+i,f1+n+1,np)-f1-1;
        kq=lower_bound(f2+i,f2+n+1,nq)-f2-1;
        if(kp < kq)    cp++,last=1;
        else cq++,last=2;
        i=min(kp,kq)+1;
    }    
    if(cp==cq || i!=n )    return;
    if(last==1&& cp>cq)    b[++ans].t=x,b[ans].s=cp;else
    if(last==2&& cp<cq)    b[++ans].t=x,b[ans].s=cq;
    return;
}
int main()
{
    freopen("game.in","r",stdin);freopen("game.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(a[i]==1) f1[i]++;else f2[i]++;
        f1[i]+=f1[i-1],f2[i]+=f2[i-1];
    }
    for(int i=1;i<=n;i++)
        work(i);
    sort(b+1,b+1+ans,cmp);
    printf("%d
",ans);
    for(int i=1;i<=ans;i++)    
        printf("%d %d
",b[i].s,b[i].t);    
    return 0;
} 
原文地址:https://www.cnblogs.com/CLGYPYJ/p/7245183.html