Codeforces - 496D
给定一个长度为 N的网球比赛的记录
网球比赛胜者要赢 S场,每场胜者要赢 T球
问所有符合条件的 S和 T的可能取值
枚举 T的值,然后判断是否有符合条件的 S
通过二分来查找每场的结束位置
总的复杂度为
(Nlog(N)log(N))
关于 s是否合法,有挺多条件的,我刚开始没想周全
- 如果在二分最后一场的时候,没有人能赢 T球,则不合法
- 最后双方胜场数一样,不合法
- 胜场数较多的那个人,与最后一场的胜者不是一个人,不合法
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <string>
#include <complex>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("\n----------")
const int maxn=1e5+10;
int N;
int in[maxn], psum[2][maxn];
int solve(int);
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
while(~scanf("%d", &N))
{
vector<Pii> ans;
for(int i=1; i<=N; i++)
{
scanf("%d", &in[i]);
psum[0][i] = psum[0][i-1];
psum[1][i] = psum[1][i-1];
psum[in[i]-1][i]++;
}
for(int t=1,s; t<=N; t++)
{
s = solve(t);
if(~s) ans.push_back({s,t});
}
sort(ans.begin(), ans.end());
cout << ans.size() << "\n";
for(Pii now:ans) cout << now.first << " " << now.second << "\n";
}
return 0;
}
int solve(int t)
{
int p=0, s[2]={0}, last=0;
while(p<N)
{
int p1 = lower_bound(psum[0]+p+1, psum[0]+N+1, psum[0][p]+t) - psum[0];
int p2 = lower_bound(psum[1]+p+1, psum[1]+N+1, psum[1][p]+t) - psum[1];
// printf("p1:%d p2:%d\n", p1, p2);
if(p1>N && p2>N) return -1;
p = min(p1, p2);
if(p1<p2) s[0]++, last=0;
else s[1]++, last=1;
}
if(s[0]==s[1]) return -1;
if(s[0]>s[1] && last==1) return -1;
if(s[0]<s[1] && last==0) return -1;
return max(s[0], s[1]);
}