Codeforces Round #562 (Div. 2) (C - E )题解

C. Increasing by Modulo

这个题是 一个 二分答案题。 

首先我们二分一个值出来,然后 check, 关键是如何 check。

 我们首先假定最小的一个值 是 0, 

然后遍历一遍数组,把数组上的值在允许的范围内尽量改小就好,

如果最后满足题目要求,那么这个二分的数就是满足条件的。 

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
int a[N],b[N],n,m;

bool check(int k){
    int cnt = 0,tmp;
    for (int i = 0; i < n; ++i){
        if (a[i] >= cnt){
            tmp = (m - a[i]) + cnt;
            if (tmp > k) cnt = a[i];
        } else {
            tmp = (cnt - a[i]);
            if (tmp > k) return false;
        }
    }
    return true;
}


int main(){
    int l = 0, r = N - 10,mid;
    scanf("%d%d",&n,&m);
    for (int i = 0; i < n; ++i)
        scanf("%d",&a[i]);
    int ans;
    while(l <= r){
        mid = (l + r) >> 1;
        if (check(mid)){
            r = mid - 1;
            ans = mid;
        } else l = mid + 1;
    }
    printf("%d\n",ans);
    return 0;
}

 

D - Good Triple

直接暴力就可以了, 

for 循环一边数据,然后暴力向前找满足题目要求的点, ans 加上去就好了。

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
int n;
char s[N];

int main(){
    long long ans = 0,l = 0;
    scanf("%s",s+1);
    n = strlen(s+1);
    for (int i = 3; i <= n; ++i){
        for (int j = i - 2; j >= l; j -= 2)
            if (s[i] == s[j] && s[(i + j) >> 1] == s[i]){l = j; break; }
        ans += l;
    }
    printf("%lld\n",ans);
    return 0;
}

E - And Reachability

 我们有 f[i][j] 代表 从i 这个位置开始, 最小能到达的位置 y ,这个 y 位置上的值 的二进制的 j 位是1,且从 i 位置到 y 位置,满足题目要求。 

即  相当于  i 为 题目中的 x, y 为 y,且 y 位置上的 数的二进制的 j 位 为 1。

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
const int INF = 0x3f3f3f3f;

int a[N],w[25],f[N][25];
int n,m;
void init(){
    memset(f, INF , sizeof f);
    memset(w , -1 , sizeof w);
    for (int i = 1; i <= n; ++i)
        scanf("%d",&a[i]);
    for (int i = n; i > 0; --i)
        for (int j = 0; j < 25; ++j)
            if ((a[i] >> j) & 1){
                for (int k = 0; k < 25; ++k)
                    if (w[j] != -1) f[i][k] = min(f[i][k],f[w[j]][k]);
                w[j] = i; f[i][j] = min(f[i][j],i);
            }
}


int main(){
    scanf("%d%d",&n,&m);
    init();
    int x,y;
    bool vis;
    for (int i = 0; i < m; ++i){
        scanf("%d%d",&x,&y);
        vis = 0;
        for (int j = 0; j < 25; ++j)
            if ((a[y] >> j)&1 && (f[x][j] <= y)){
                vis = 1; break;
            }
        vis == 1? puts("Shi"): puts("Fou");
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值