Codeforces 496D

类似于模拟,记录下标或者二分进行优化

#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

struct node {
    int u, v;
    bool operator < (const node& rhy) const {
        if(u != rhy.u) return u < rhy.u;
        return v < rhy.v;
    }
}ans[101010];

int n;
int b[101010], sum1[101010], sum2[101010], in1[101010], in2[101010];
bool vis[101010];
int main(){
    while(scanf("%d", &n) == 1) {
        sum1[0] = sum2[0] = 0;
        memset(in1, 0x7f7f7f7f, sizeof(in1));
        memset(in2, 0x7f7f7f7f, sizeof(in2));
        for(int i = 1; i <= n; ++ i) {
            int x;
            scanf("%d", &x);
            b[i] = x;
            if(x == 1) {
                sum1[i] = 1;
                sum2[i] = 0;
                sum1[i] += sum1[i-1];
                sum2[i] += sum2[i-1];
                in1[sum1[i]] = i;
            }
            else {
                sum1[i] = 0;
                sum2[i] = 1;
                sum1[i] += sum1[i-1];
                sum2[i] += sum2[i-1];
                in2[sum2[i]] = i;
            }
        }
        int dd = 0;
        if(b[n] == 1) {
            for(int i = 1; i <= sum1[n]; ++ i) {
                if(i > sum2[n]) {
                    if(sum1[n]%i == 0) {
                        ans[dd].u = sum1[n]/i;
                        ans[dd].v = i;
                        dd ++;
                    }
                    continue;
                }
                int now = 0;
                int cc1 = 0, cc2 = 0, w1 = 0, w2 = 0;
                while(now < n) {
                    if(in1[w1+i] < in2[w2+i]) {
                        w1 = w1+i;
                        cc1 ++;
                        now = in1[w1];
                        w2 = sum2[now];
                    }
                    else if(in1[w1+i] > in2[w2+i]){
                        cc2 ++;
                        w2 = w2+i;
                        now = in2[w2];
                        w1 = sum1[now];
                    }
                    else break;
                }
                if(now == n && cc1 > cc2) {
                    ans[dd].u = cc1;
                    ans[dd].v = i;
                    dd ++;
                }
            }
        }
        else {
            for(int i = 1; i <= sum2[n]; ++ i) {
                if(i > sum1[n]) {
                    if(sum2[n]%i == 0) {
                        ans[dd].u = sum2[n]/i;
                        ans[dd].v = i;
                        dd ++;
                    }
                    continue;
                }
                int now = 0;
                int cc1 = 0, cc2 = 0, w1 = 0, w2 = 0;
                while(now < n) {
                    if(in1[w1+i] > in2[w2+i]) {
                        w2 = w2+i;
                        cc1 ++;
                        now = in2[w2];
                        w1 = sum1[now];
                    }
                    else if(in1[w1+i] < in2[w2+i]){
                        cc2 ++;
                        w1 = w1+i;
                        now = in1[w1];
                        w2 = sum2[now];
                    }
                    else break;
                }
                if(now == n && cc1 > cc2) {
                    ans[dd].u = cc1;
                    ans[dd].v = i;
                    dd ++;
                }
            }
        }
        sort(ans, ans+dd);
        printf("%d\n", dd);
        for(int i = 0; i < dd; ++ i)
            printf("%d %d\n", ans[i].u, ans[i].v);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值