码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #637 (Div. 2)

时间:2020-04-24 22:09:11      阅读:106      评论:0      收藏:0      [点我收藏+]

标签:组合   a+b   取出   ack   代码   const   ring   its   clu   

比赛链接:https://codeforces.com/contest/1341

A - Nastya and Rice

题意

有 n 堆米,每堆质量在 [a-b,a+b] 之间,这些米的总质量是否可能在 [c-d,c+d] 之间。

思路

n 堆米的最小总质量为 n*(a-b),最大总质量为 n*(a+b),即判断区间 [n*(a-b),n*(a+b)] 是否与 [c-d,c+d] 相交。

代码一

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n, a, b, c, d; cin >> n >> a >> b >> c >> d;
    int mi = n * (a - b);
    int mx = n * (a + b);
    if (c + d < mi or c - d > mx)
        cout << "No" << "\n";
    else 
        cout << "Yes" << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

代码二

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n, a, b, c, d; cin >> n >> a >> b >> c >> d;
    int mi = n * (a - b);
    int mx = n * (a + b);
    if ((mx >= c + d and mi <= c + d) or (mi <= c - d and mx >= c - d) or (mi >= c - d and mx <= c + d))
        cout << "Yes" << "\n";
    else 
        cout << "No" << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

B - Nastya and Door

题意

有一数组 a,定长 k 最多能完整覆盖多少 a[i-1] < a[i] 且 a[i] > a[i+1] 的长为 3 的区间,不考虑数组两端。

思路一

前缀和记录每个端点为止的符合条件的区间数量,之后枚举定长的起始点,覆盖区间的右端点需要再减一来错峰。

代码一

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n, k; cin >> n >> k;
    int a[n + 1]= {}; 
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    int cnt[n + 1] = {};
    for (int i = 1; i <= n; i++) {
        cnt[i] += cnt[i - 1];
        if (a[i] > a[i - 1] and a[i] > a[i + 1]) 
            ++cnt[i];
    }
    int mx = 1, st = 1;
    for (int i = 1; i + k - 1 <= n; i++) {
        int l = i, r = i + k - 2;
        int sub = cnt[r] - cnt[l] + 1;
        if (sub > mx) mx = sub, st = l;
    }
    cout << mx <<   << st << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

思路二

记录所有符合条件区间的左右端点,对于每个枚举的起始点二分查找最近的区间左右端点。

代码二

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n, k; cin >> n >> k;
    int a[n + 1]; for (int i = 1; i <= n; i++) cin >> a[i];
    vector<int> l, r;
    for (int i = 2; i <= n - 1; i++) {
        if (a[i - 1] < a[i] and a[i] > a[i + 1]) {
            l.push_back(i - 1);
            r.push_back(i + 1);
        }
    }
    int mx = 1, st = 1;
    for (int i = 1; i <= n; i++) {
        int lf = lower_bound(l.begin(), l.end(), i) - l.begin();
        int rt = upper_bound(r.begin(), r.end(), i + k - 1) - r.begin();
        if (rt > 0 and rt - lf + 1 > mx) {
            mx = rt - lf + 1;
            st = i;
        }
    }
    cout << mx <<   << st << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

C - Nastya and Strange Generator

题意

[1,2,3,...,n] 中每次可从一点起向右连续取完所有未取过的数,取出的这些数列的所有组合中是否有当前排列。

思路

因为是连续取的所以不会出现隔点取的情况,据此判断即可。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n; cin >> n;
    int a[n]; for (int &i : a) cin >> i;
    for (int i = 0; i + 1 < n; i++) {
        if (a[i + 1] - a[i] >= 2) {
            cout << "No" << "\n";
            return;
        }
    }
    cout << "Yes" << "\n";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

D - Nastya and Scoreboard

题意

有一液晶数字板,其中亮着一些段,问再点亮 k 段所能构成的最大数字。

思路

从后向前构造,dp[i][j] 表示构造到第 i 位时用 j 段是否可行,dp[0][k] 可行即有解(0-indexed)。因为在 dp 的过程中每一位每一种可行的情况都是与之后一系列的位相关联的,所以其实当输出第一位的最大可行数字后后面一系列的位就已经确定了。

代码

#include <bits/stdc++.h>
using namespace std;

const int M = 2200;

string str[10] = {"1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011"};
int a[M], s[10];
bool ok[M][8], dp[M][M];

int main() {
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 7; j++) {
            s[i] = 2 * s[i] + str[i][j] - 0;
        }
    }
    int n, k; cin >> n >> k;
    for (int i = 0; i < n; i++) {
        int a_i = 0;
        for (int j = 0; j < 7; j++) {
            char c; cin >> c;
            a_i = 2 * a_i + c - 0;
        }
        a[i] = a_i;
        for (int j = 0; j < 10; j++) {
            if ((a[i] & s[j]) == a[i]) {
                int cnt = __builtin_popcount(a[i] ^ s[j]);
                ok[i][cnt] = true;
            }
        }
    }
    dp[n][0] = true;
    for (int i = n - 1; i >= 0; i--) 
        for (int j = 0; j < M; j++)
            if (dp[i + 1][j])
                for (int k = 0; k <= 7; k++)
                    if (ok[i][k])
                        dp[i][j + k] = true;
    if (!dp[0][k]) cout << "-1";
    else {
        for (int i = 0; i < n; i++)
            for (int j = 9; ; j--)
                if ((a[i] & s[j]) == a[i]) {
                    int cnt = __builtin_popcount(a[i] ^ s[j]);
                    if (dp[i + 1][k - cnt]) {
                        k -= cnt; cout << j;
                        break;
                    }
                }
    }
}

 

Codeforces Round #637 (Div. 2)

标签:组合   a+b   取出   ack   代码   const   ring   its   clu   

原文地址:https://www.cnblogs.com/Kanoon/p/12766761.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!