Codeforces Round #283 (Div. 2)D. Tennis Game

题意:给出比赛情况,输出所有满足条件的s,t,使得这场比赛有结果。

枚举t,然后二分找得分为t的下界,并更新每局的边界,判断谁获得当前局的胜利。最后的时候要注意判断最后一局的赢家是否是整场比赛的赢家。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <bitset>
#include <queue>
#include <stack>
#include <string>
#include <iostream>
#include <cmath>
#include <climits>

using namespace std;

const int maxn = 111111;
const int INF = 0xfffffff;
int sum1[maxn];
int sum2[maxn];
int n;
int a[maxn];
int erfen1(int l,int r,int key)
{
    int ans = INF;
    int k = l;
    while(l<=r){
        int mid=(l+r)>>1;
        if(sum1[mid]-sum1[k-1] == key) ans=mid;
        if(sum1[mid]-sum1[k-1] >= key) r = mid-1;
        else l = mid+1;
    }
    return ans;
}
int erfen2(int l,int r,int key)
{
    int ans = INF;
    int k = l;
    while(l<=r){
        int mid=(l+r)>>1;
        if(sum2[mid] - sum2[k-1]==key) ans = mid;
        if(sum2[mid] - sum2[k-1]>=key) r = mid-1;
        else l = mid+1;
    }
    return ans;
}
int judge(int t)
{
    int ans1 = 0;int ans2 = 0;
    int l = 1;
    while(l<=n){
        int t1 = erfen1(l,n,t);
        int t2 = erfen2(l,n,t);
        l = min(t1,t2) + 1;
        if(l>n+1) return 0;
        if(t1==t2&&t1==INF) continue;
        if(t1<t2) ans1++;
        else ans2++;
        if(l-1==n){
            if(ans1>ans2&&t1>t2) return 0;
            if(ans2>ans1&&t2>t1) return 0;
        }
    }
    if(ans1==ans2) return 0;
    return ans1>ans2? ans1:ans2;
}

struct Node
{
    int x;int y;
};
int cmp(const Node &a,const Node & b)
{
    return a.x<b.x;
}
vector<Node > q;
int main()
{
    cin>>n;
    memset(sum2,0,sizeof(sum2));
    memset(sum1,0,sizeof(sum1));
    for(int i = 1;i<=n;i++){
        scanf("%d",&a[i]);
        if(a[i]==1) sum1[i] = 1;
        else sum2[i] = 1;
    }
    for(int i =1;i<=n;i++)
        sum1[i]+=sum1[i-1],sum2[i]+=sum2[i-1];
    for(int t = 1;t<=n;t++){
        int gg = judge(t);
        if(gg==0) continue;
        Node k ; k.x = gg; k.y = t;
        q.push_back(k);
    }
    sort(q.begin(),q.end(),cmp);
    printf("%d\n",q.size());
    for(int i = 0;i<q.size();i++)
        printf("%d %d\n",q[i].x,q[i].y);
    return 0;
}
时间: 2024-10-12 22:30:52

Codeforces Round #283 (Div. 2)D. Tennis Game的相关文章

Codeforces Round #283 Div.2 D Tennis Game --二分

题意: 两个人比赛,给出比赛序列,如果为1,说明这场1赢,为2则2赢,假如谁先赢 t 盘谁就胜这一轮,谁先赢 s 轮则赢得整个比赛.求有多少种 t 和 s 的分配方案并输出t,s. 解法: 因为要知道有哪些t,s,那么我们至少要枚举一个量,然后才能得出所有分配方案,由题意似乎枚举 t 比较方便.由于 n <= 10^5, 那么我们必须在平均logn算法级以下判断此 t 合不合法,即有没有合法的 s .经过一些预处理,或者二分都可以达到logn的算法. 预处理sum1[i], sum2[i] 分别

Codeforces Round #283 (Div. 2) a

/**  * @brief Codeforces Round #283 (Div. 2) a  * @file a.cpp  * @author mianma  * @created 2014/12/18 17:45  * @edited  2014/12/18 17:45  * @type brute  * @note  */ #include <fstream> #include <iostream> #include <cstring> using namespa

构造+暴力 Codeforces Round #283 (Div. 2) B. Secret Combination

题目传送门 1 /* 2 构造+暴力:按照题目意思,只要10次加1就变回原来的数字,暴力枚举所有数字,string大法好! 3 */ 4 /************************************************ 5 Author :Running_Time 6 Created Time :2015-8-3 8:43:02 7 File Name :A.cpp 8 *************************************************/ 9 1

暴力+构造 Codeforces Round #283 (Div. 2) C. Removing Columns

题目传送门 1 /* 2 题意:删除若干行,使得n行字符串成递增排序 3 暴力+构造:从前往后枚举列,当之前的顺序已经正确时,之后就不用考虑了,这样删列最小 4 */ 5 /************************************************ 6 Author :Running_Time 7 Created Time :2015-8-3 10:49:53 8 File Name :C.cpp 9 ************************************

Codeforces Round #283 (Div. 2) c

/**  * @brief Codeforces Round #283 (Div. 2) c  * @file c.cpp  * @author mianma  * @created 2014/12/22 13:38  * @edited  2014/12/22 13:38  * @type greedy  * @time cost time O(m*n)  * @mem  cost mem  2*MAXN^2 + 2*MAXN  * @note  */ #include <fstream>

Codeforces Round #283 (Div. 2) b

/**  * @brief Codeforces Round #283 (Div. 2) b  * @file b.cpp  * @author mianma  * @created 2014/12/19 10:50  * @edited  2014/12/19 10:50  * @type brute  * @note  */ #include <fstream> #include <iostream> #include <cstring> using namespa

Codeforces Round #283 (Div. 2) D,E

D: 题目大意:两个人进行比赛,我们只知道进行了N局比赛的结果,N局之后有一个人赢得了最终的比赛.1代表第一个人赢,2代表第二个人赢.给你他们的输赢情况,让你求出来怎么安排比赛才能得到这种情况,输出时,先按S排序,如果S相同按照T排序.按顺序输出所有的S,T. 思路:我们可以预处理出来在第几的位置某个人赢了x场. 比如: 8 2 1 2 1 1 1 1 1 我们需要枚举赢k场比赛算赢了一小场,注意最后赢的人一定必须是这一局的胜利者. 枚举k之后我们从0开始向后找比如k = 2, xpos代表1赢

Codeforces Round #283 (Div. 1)解题报告A.B.C.

A - Removing Columns 贪心. 只能是竖着不递减的就尽量选上,当某一行出现字典序大于上一行的情况的时候,就不用再考虑这一行. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #inc

Codeforces Round #283 (Div. 2)C、D、E题解

C. Removing Columns https://codeforc.es/contest/496/problem/C 从前往后标记那些前面已经确定字典序合法的行,对于字典序不合法又没被标记的直接删除该列. 1 #define bug(x) cout<<#x<<" is "<<x<<endl 2 #define IO std::ios::sync_with_stdio(0) 3 #include <bits/stdc++.h&g