Codeforces Round #380 (Div. 2, Rated, Based on Technocup 2017 - Elimination Round 2)

A. Interview with Oleg

这道题主要就是判断ogo,如果前一个ogo与后一个ogo相连(也就是说前一个ogo的最后一个o作为后一个ogo的最前面的o),那么可认为这些ogo是一个部分,用 代替即可。

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 1005
char s[maxn];

bool judge(char a[], int i){
    if(a[i] == 'o' && a[i+1] == 'g' && a[i+2] == 'o') return true;
    return false;
}

int main(){
    int n;
    memset(s, '\0', sizeof(s));
    scanf("%d %s", &n, s);
    int i = 0;
    int flag = 0;
    vector <char> vec;
    while(i < n){
        if(judge(s, i)) i += 2, flag = 1;
        else{
            if(flag) vec.push_back('*'),vec.push_back('*'),vec.push_back('*');
            else vec.push_back(s[i]);
            i++;
            flag = 0;
        }
    }
    for(int i = 0; i < vec.size(); i++)
        printf("%c", vec[i]);
    printf("\n");
    return 0;
}

B. Spotlights

这道题我的想法就是找到一个1然后往4个方向延展即可,计算一下会发现每一个0的位置最多被计算4次,也就是每次的时间复杂度为: O(4nm)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1005;
#define LL long long
int a[maxn][maxn];

int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            scanf("%d", &a[i][j]);
    LL ans = 0;
    for(int i = 1; i <= n; i++)
    for(int j = 1; j <= m; j++){
        if(a[i][j] == 1){
            for(int k = j-1; k >= 1; k--){
                if(a[i][k] == 0) ans++;
                else break;
            }
            for(int k = j+1; k <= m; k++){
                if(a[i][k] == 0) ans++;
                else break;
            }
            for(int k = i-1; k >= 1; k--){
                if(a[k][j] == 0) ans++;
                else break;
            }
            for(int k = i+1; k <= n; k++){
                if(a[k][j] == 0) ans++;
                else break;
            }
        }
    }
    printf("%I64d\n", ans);
    return 0;
}

C. Road to Cinema

c题题目挺长的不过挺容易理解的,我比赛的时候估计脑子抽了,真的太傻了,居然数学公式都没有推出来,其实也就是解个方程而已,服了自己。具体做法就是对每个车的汽油容量进行排序,然后二分查找能满足条件的最小的汽油容量,然后for循环跑一遍找到其中最小的价钱即可。对于二分里面的判断其实我一直都想复杂了,然后后来发现很简单。假设汽车以第一种方式的用油量是x,那么第二种方式的用油量是v-x,那么即可得到x+(v-x)/2 = a[i] (a[i]表示2个相邻汽油站之间的距离),解得x = 2*a[i]-v;于是这段所需要的时间就是3*a[i]-v;

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 2e5+100;
const LL INF = 0x3f3f3f3f3f3f3f3f;

struct Node{
    LL c, v;
}car[maxn];

int a[maxn];

bool check(int mid, int a[], int len, int t){
    LL ans = 0;
    for(int i = 1; i <= len; i++){
        if(a[i] > mid) return false;
        else if(2*a[i] <= mid) ans += a[i];
        else ans += 3*a[i] - mid;
    }
    return ans <= t;
}



int main(){
    LL n, k, s, t;
    scanf("%I64d%I64d%I64d%I64d", &n, &k, &s, &t);
    for(int i = 0; i < n; i++) scanf("%I64d%I64d", &car[i].c, &car[i].v);
    for(int i = 1; i <= k; i++) scanf("%d", &a[i]);
    a[0] = 0;
    a[++k] = s;
    sort(a, a+k+1);
    for(int i = k; i >= 1; i--) a[i] -= a[i-1];
    LL l = 1, r = 1e9+100;
    while(l < r){
        LL mid = (l+r)/2;
        if(check(mid, a, k, t)) r = mid;
        else l = mid+1;
    }
    LL ans = INF;
    for(int i = 0; i < n; i++)
        if(car[i].v >= r) ans = min(ans, car[i].c);
    if(ans < INF) printf("%I64d\n", ans);
    else printf("-1");
    return 0;
}

D. Sea Battle

一个比较恶心的模拟题,比赛的时候写的有点慢,其实题目给出的n和k可以忽略,没有什么作用,然后就是找每一段连续的0,那么这一段能放的船数最多为 flag/b ,然后模拟处理一下即可。

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5+100;

char s[maxn];

int main(){
    int n, a, b, k;
    scanf("%d%d%d%d", &n, &a, &b, &k);
    scanf("%s", s);
    int flag = 0, ans = 0;
    for(int i = 0; i < n; i++){
        if(s[i] == '0') flag++;
        else{
            if(flag >= b) ans += flag/b;
            flag = 0;
        }
    }
    if(flag >= b) ans += flag/b;
    printf("%d\n", ans - a + 1);
    flag = 0;
    ans = ans - a + 1;
    for(int i = 0; i < n; i++){
        if(s[i] == '0') flag++;
        else{
            if(flag >= b){
                int cnt = flag/b;
                int temp = i;
                while(cnt > 0 && ans > 0){
                    temp -= b;
                    printf("%d ", temp+1);
                    cnt--;
                    ans--;
                }
                if(ans == 0) break;
            }
            flag = 0;
        }
    }
    if(ans != 0 && flag >= b){
        int cnt = flag/b;
        int temp = n;
        while(cnt > 0 && ans > 0){
            temp -= b;
            printf("%d ", temp+1);
            cnt--;
            ans--;
        }
    }
    return 0;
}

E. Subordinates

对于这颗关系树来说我们可以通过枚举树的最大深度来求得答案,对于高为n的关系树,首先我们需要知道这个关系树中有哪里高度是不存在的,假设为cnt,那么对于高于关系树的部分和(高度为0但是不是chief的部分)与cnt相比取最大值即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5+100;
const int INF = 0x3f3f3f3f;
int a[maxn], c[maxn], sum[maxn];

int main(){
    int n, s;
    scanf("%d%d", &n, &s);
    int flag = 0;
    memset(a, 0, sizeof(a));
    memset(sum, 0, sizeof(sum));
    memset(c, 0, sizeof(c));
    for(int i = 1; i <= n; i++){
        scanf("%d", &a[i]);
        if(i == s){
            if(a[i] != 0) flag = 1;
        }
        else c[a[i]]++;
    }
    if(n == 1){
        if(flag) printf("1\n");
        else printf("0\n");
        return 0;
    }
    for(int i = 1; i < n; i++) sum[i] = sum[i-1] + c[i];

    int ans = INF, cnt = 0;
    for(int i = 1; i < n; i++){
        if(!c[i]) cnt++;
        ans = min(ans, flag + max(c[0] + sum[n-1] - sum[i], cnt));
    }
    printf("%d\n", ans);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值