CF_496 D-Tennis Game(二分)

D. Tennis Game
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Petya and Gena love playing table tennis. A single match is played according to the following rules: a match consists of multiple sets, each set consists of multiple serves. Each serve is won by one of the players, this player scores one point. As soon as one of the players scores t points, he wins the set; then the next set starts and scores of both players are being set to 0. As soon as one of the players wins the total of s sets, he wins the match and the match is over. Here s and t are some positive integer numbers.

To spice it up, Petya and Gena choose new numbers s and t before every match. Besides, for the sake of history they keep a record of each match: that is, for each serve they write down the winner. Serve winners are recorded in the chronological order. In a record the set is over as soon as one of the players scores t points and the match is over as soon as one of the players wins s sets.

Petya and Gena have found a record of an old match. Unfortunately, the sequence of serves in the record isn't divided into sets and numbers s and t for the given match are also lost. The players now wonder what values of s and t might be. Can you determine all the possible options?

Input

The first line contains a single integer n — the length of the sequence of games (1 ≤ n ≤ 105).

The second line contains n space-separated integers ai. If ai = 1, then the i-th serve was won by Petya, if ai = 2, then the i-th serve was won by Gena.

It is not guaranteed that at least one option for numbers s and t corresponds to the given record.

Output

In the first line print a single number k — the number of options for numbers s and t.

In each of the following k lines print two integers si and ti — the option for numbers s and t. Print the options in the order of increasingsi, and for equal si — in the order of increasing ti.

Sample test(s)
input
5
1 2 1 2 1
output
2
1 3
3 1
input
4
1 1 1 1
output
3
1 4
2 2
4 1
input
4
1 2 1 2
output
0
input
8
2 1 2 1 1 1 1 1
output
3
1 6
2 3
6 1

题意:

两个人进行网球比赛,赢一球得一分,每局有T分,一局胜利后比分会被刷新,当某人赢够S局后比赛结束;现 在输入n个数,表示一场比赛中两个人的分别得分,1表示Petya , 2表示Gena. 要求依据这组得分输出所有可能 的比分回合制度,顺序为以S递增,S相同以T递增。

题解:

这道题的关键在于理解好题意,题目要求输出所有可能的回合制,我们可以由1至最大得分枚举所有情况,然 后再每次判断是否满足比赛规则。

注意点:

对于得分的处理是关键,如果从头至尾遍历时间复杂度为O(n*n),一定会超时,所以可以再输入的时候直 接把得分转化为当前每个人的总得分存储,这样可以在每次的 判断中利用二分查找,定位最先达到满足分 数的人,胜局加一。当一局比赛结束后,得分会被刷新,所以每局结束时都要将两人得分同步到胜者的当 前位置,再进行下一次运算。

不满足题意的情况:

1.以T分制计算,最终结束时未打满一整局;

2.winner与得分最高的人不相同;

3.两个人得分相同;


代码实现:

<span style="font-size:14px;">#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

struct option{
    int s;
    int t;
    bool operator <(const option &next) const
    {
        if(this->s==next.s)
            return this->t < next.t;
        else
            return this->s < next.s;
    }
};//定义结构体储存满足条件的回合制度,重载'<'号方便后期sort排序
vector<int> num1;//储存'1'总得分
vector<int> num2;//储存'2'总得分
vector<option> oLis;//储存
int n,sum1,sum2;
int winner;//将胜者(who get the key point)标记
bool solve(int);
int main()
{
    scanf("%d",&n);int a;
    sum1=0;sum2=0;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a);
        if(a==1)
            sum1++;
        else
            sum2++;
        if(i==n-1)
            winner=a;
        num1.push_back(sum1);
        num2.push_back(sum2);
    }
    int sum=sum1>sum2?sum1:sum2;
    for(int i=1;i<=sum;i++)//从1到最大得分枚举
        solve(i);
    sort(oLis.begin(),oLis.end());
    printf("%d\n",oLis.size());
    for(int i=0;i<(int)oLis.size();i++)
        printf("%d %d\n",oLis[i].s,oLis[i].t);
    return 0;
}
bool solve(int x)
{
    int tmp1,tmp2;//储存最先达到指定分数的位置
    int pos1,pos2;//储存1,2当前实际得分
    int score1,score2;//储存1,2所赢回合数
    bool flag=true;
    pos1=0;pos2=0;
    score1=0;score2=0;
    for(int i=0;i<n;i++)
    {
        //二分找到最早满足得分的回合
        tmp1=lower_bound(num1.begin(),num1.end(),pos1+x)-num1.begin();
        tmp2=lower_bound(num2.begin(),num2.end(),pos2+x)-num2.begin();
        if(tmp1!=n||tmp2!=n)//必须当两人都达到最高得分时跳出循环
        {
            if(tmp1<tmp2)//1先满足条件
            {
                score1++;
                //同步得分:将两人当前得分定位到同一位置
                pos1=num1[tmp1];
                pos2=num2[tmp1];
            }
            else
            {
                score2++;
                pos1=num1[tmp2];
                pos2=num2[tmp2];
            }
        }
        else//两人同时达到最高分
        {
            tmp1=tmp2=n-1;
            //此时表示结束时仍未打完一局
            if(num1[tmp1]!=pos1||num2[tmp2]!=pos2)
                flag=false;
            break;
        }
    }
    if(flag)
    {
        //不满足题意情况
        if((winner==1&&score2>score1)||(winner==2&&score1>score2)||(score1==score2))
            return false;
        option tem;
        tem.s=score1>score2?score1:score2;
        tem.t=x;
        oLis.push_back(tem);
        return true;
    }
    return false;
}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值