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?
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.
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 increasing si, and for equal si — in the order of increasing ti.
5 1 2 1 2 1
2 1 3 3 1
4 1 1 1 1
3 1 4 2 2 4 1
4 1 2 1 2
0
8 2 1 2 1 1 1 1 1
3 1 6 2 3 6 1
解题思路:大致意思是一个比赛里面包含多个回合, 每回合谁优先拿到t分就算赢得这局的胜利,而谁优先拿到S局的胜利,就获得整场比赛的胜利。问有几种S和t的组合方法。
样例一:比赛的得分序列是1 2 1 2 1。其中1表示选手1得分, 2表示选手2得分。
输出有两种组合方式。
可以是得3分赢一局,总共为1局。那么1 2 1 2 1 就是一局比赛,这一局中选手1得3分,选手2得2分。
也可以是得1分赢一局,那么1 2 1 2 1的结果就是选手1赢3局,选手2赢了2局。那么为了满足题意设定,s就必须为3局,即谁先拿下三局就获得整场比赛胜利。
虽然知道方法是二分,但是比较难下手。
突破口是输入的时候保存两位选手在每次pk时【累计】的得分。
接下来就是枚举每局比赛需要的得分i。在第一局中用二分找到两个人得分为i的位置,谁的位置靠前,第一局就由谁胜出。
之后的每一局的查找位置从上一局结束的位置开始找,两位选手要找的分数都是上一局结束位置两人的分别是s1, s2得分加上i。
要注意的是最后一个得分的一定是赢家(平局除外)。
如果两个人在查找时同时到了各自得分序列最后, 那么说明枚举的i就是不合法的。
/********************************/
/*Problem: codeforces #496D# */
/*User: shinelin */
/*Memory: 1800 KB */
/*Time: 109 ms */
/*Language: GNU C++ */
/********************************/
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <cstring>
#include <string>
#include <list>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <set>
#include <algorithm>
#include <cmath>
using namespace std;
#define INF 0x7fffffff
#define LL long long
struct Comm
{
int first;
int second;
Comm(int a, int b)
{
first = a;
second = b;
}
bool operator <(const Comm& other) const
{
if(this->first == other.first)
return this->second < other.second;
return this->first < other.first;
}
};
vector<int> P;
vector<int> G;
vector<Comm> ans;
int n;
int main()
{
int x, scoP = 0, scoG = 0;
scanf("%d", &n);
for (int i = 0; i < n; i ++)
{
scanf("%d", &x);
if(x == 1)
scoP ++;
else
scoG ++;
P.push_back(scoP);
G.push_back(scoG);
}
int pntP = 0, pntG = 0, setP = 0, setG = 0;
int maxPoint = max(scoP, scoG);
for (int i = maxPoint; i > 0; i --)
{
int tar1 = i, tar2 = i; //初始化拿下第一局需要的分数
int pos = 0; //查找的位置
setP = setG = pntG = pntP = 0;
while(pos < n && !(pntG == pntP && pntG == n))
{
pntP = lower_bound(P.begin() + pos, P.end(), tar1) - P.begin();
pntG = lower_bound(G.begin() + pos, G.end(), tar2) - G.begin();
if(pntP < pntG)
{
setP ++;
pos = pntP + 1;
tar1 = P[pntP] + i;
tar2 = G[pntP] + i;
}
if(pntP > pntG)
{
setG ++;
pos = pntG + 1;
tar1 = P[pntG] + i;
tar2 = G[pntG] + i;
}
}
int tmp = max(setG, setP);
if(tmp == setG && x == 1 || tmp == setP && x == 2 //x是最后一次输入。
|| setG == setP || pntG == pntP && pntG == n)
{
continue;
}
Comm m(tmp, i);
ans.push_back(m);
}
printf("%d\n", ans.size());
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); i ++)
{
printf("%d %d\n", ans[i].first, ans[i].second);
}
return 0;
}