Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3)

A - Math Problem

题意:给n条线段[l,r],求再加一条可以退化成点的线段,与所有线段各至少有一个公共点。

题解:求出最右边的左端点和最左边的右端点,左端点>右端点,则说明你的这个线段要把这两个连起来,否则你的线段就是现在的[左端点,右端点]上的随便一个点。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
void test_case() {
    int n;
    scanf("%d", &n);
    int L = 1, R = 1e9;
    for(int i = 1; i <= n; ++i) {
        int l, r;
        scanf("%d%d", &l, &r);
        L = max(L, l);
        R = min(R, r);
    }
    int ans = 0;
    if(L > R)
        ans = L - R;
    printf("%d\n", ans);
}
 
int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t = 1;
    scanf("%d", &t);
    for(int ti = 1; ti <= t; ++ti) {
        //printf("Case #%d: ", ti);
        test_case();
    }
}

B - Box

题意:给一个前缀最大值序列,求满足这个序列的任意一个排列。

题解:生成的是满足这个序列的字典序最大的一个排列。而实际上因为这个序列是递增的,怎么乱构造都可以。首先每次最大值变化的位置肯定放这个罪魁祸首,然后扫一遍之后可能会有一些位置没有放,这个时候lower_bound其最大值得到大于等于其最大值的任意一个值。然后--之后就是小于它的最大的一个值,把它放过去就可以了。或者每次就放begin迭代器,直到begin迭代器超过最大值就-1,这样是字典序最小。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
int q[100005];
int p[100005];
set<int> tmp;
 
void test_case() {
    int n;
    scanf("%d", &n);
    tmp.clear();
    for(int i = 1; i <= n; ++i) {
        p[i] = -1;
        tmp.insert(i);
    }
    for(int i = 1; i <= n; ++i)
        scanf("%d", &q[i]);
    p[1] = q[1];
    tmp.erase(q[1]);
    for(int i = 2; i <= n; ++i) {
        if(q[i] > q[i - 1]) {
            p[i] = q[i];
            tmp.erase(q[i]);
        }
    }
    for(int i = 1; i <= n; ++i) {
        if(p[i] == -1) {
            auto t = tmp.lower_bound(q[i]);
            if(t == tmp.begin()) {
                puts("-1");
                return;
            }
            --t;
            p[i] = *t;
            tmp.erase(t);
        }
    }
    for(int i = 1; i <= n; ++i)
        printf("%d%c", p[i], " \n"[i == n]);
}
 
int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t = 1;
    scanf("%d", &t);
    for(int ti = 1; ti <= t; ++ti) {
        //printf("Case #%d: ", ti);
        test_case();
    }
}

C - Messy

题意:给一个"("")"括号相等的长度不超过2000的括号串,要求每次反转一个子区间,最后使得括号串合法,且经过零点恰好k次。

题解:贪心,每次贪心把前两个字符变成"("")",这样最后就有n/2次零点,然后把开头开始的一小段破坏掉就可以了(假如需要的话,不要画蛇添足),至多用n/2+1次。因为网络的原因没有交上去,问题不大,实力到了自然会收敛。

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

int n, k;
string s;
vector<pair<int, int> > ans;

void test_case() {
    ans.clear();
    cin >> n >> k >> s;
    int curp = 1;
    while(s.length()) {
        if(s[0] == '(' && s[1] == ')') {
            s = s.substr(2, s.length());
            curp += 2;
        } else if(s[0] == ')' && s[1] == '(') {
            ans.push_back({curp + 0, curp + 1});
            s = s.substr(2, s.length());
            curp += 2;
        } else if(s[0] == ')') {
            int j = 2;
            while(s[j] == s[0])
                ++j;
            ans.push_back({curp + 0, curp + j});
            string s1 = s.substr(0, j + 1);
            string s2 = s.substr(j + 1, s.length());
            reverse(s1.begin(), s1.end());
            s = s1 + s2;
            s = s.substr(2, s.length());
            curp += 2;
        } else {
            int j = 2;
            while(s[j] == s[0])
                ++j;
            ans.push_back({curp + 1, curp + j});
            string s0 = s.substr(0, 1);
            string s1 = s.substr(1, j);
            string s2 = s.substr(j + 1, s.length());
            reverse(s1.begin(), s1.end());
            s = s0 + s1 + s2;
            s = s.substr(2, s.length());
            curp += 2;
        }
    }
    int tk = n / 2 - k;
    if(1 + 2 * tk >= 2)
        ans.push_back({2, 1 + 2 * tk});
    cout << ans.size() << endl;
    for(int i = 0; i < ans.size(); ++i)
        cout << ans[i].first << " " << ans[i].second << endl;
}

int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t = 1;
    scanf("%d", &t);
    for(int ti = 1; ti <= t; ++ti) {
        //printf("Case #%d: ", ti);
        test_case();
    }
}

注:要注意string的substr方法的使用,真的烦死人,substr(a,b)是从a位置开始截取最多b个字符形成的子串。其实假如用静态字符数组会不会方便一些?要是自己写一个String类就可以使用自己的全新方法了。

猜你喜欢

转载自www.cnblogs.com/KisekiPurin2019/p/11924913.html