CF Global Round 15(补题)

Codeforces Global Round 15

A. Subsequence Permutation

  • 签到
  • 思路

字符串排个序,然后匹配就行了

code:


const int N = 200100;

int st[30];

void solve(){
    int n;
    string str;
    cin >> n >> str;
    string s = str;
    int ans = 0;
    sort(s.begin(), s.end());
    for(int i = 0;i < n;i ++) {
        if(s[i] == str[i]) ans ++;
    }
    cout << n - ans << endl;
}

B. Running for Gold

  • 题意

n个人,每个人有5次分数,(rank_i,_j)运动员i在第j次分数的排名情况,i比j优秀: 三次或三次以上的排名大于j即可,现需找出最优秀的人。

  • 思路

每次比较两个人的优秀,然后删掉另一个即可,最后在扫一遍,看最后剩的人会不会比别人小,输出-1

code:

struct node {
    int a,b,c,d,e;
    int id;
};
bool cmp(node a, node b) {
    int cnt = 0;
    if(a.a > b.a) cnt ++;
    if(a.b > b.b) cnt ++;
    if(a.c > b.c) cnt ++;
    if(a.d > b.d) cnt ++;
    if(a.e > b.e) cnt ++;
    return cnt < 3;
}

vector<node> v, u;

void solve(){
    int n;
    cin >> n;
    v.resize(n);
    for(int i = 0;i < n;i ++) {
        cin >> v[i].a >> v[i].b >> v[i].c >> v[i].d >> v[i].e;
        v[i].id = i + 1;
    }
    u = v;
    while(u.size() > 1) {
        if(cmp(u[0],u[1])) {
            u.erase(u.begin() + 1);
        }else {
            u.erase(u.begin());
        }
    }
    bool flag = 0;
    for(int i = 0;i < n;i ++) {
        if(cmp(v[i], u[0]) && v[i].id != u[0].id) flag = 1;
    }
    if(flag) cout << "-1" << endl;
    else cout << u[0].id << endl;
    v.clear();
}

C. Maximize the Intersections

  • 题意

一共2 * n个点,并且给出了k对弦, 要求用甚于(n - k) * 2个点进行连边,并让交点最大。

  • 思路

首先,两边相交,那么就是x1 < x2 < y1 < y2 || x2 < x1 < y2 < y1这两条,那么我们要让我们建的点最大化这一性质,通过不断话图形可以推出来一个规律,我们将所有剩余的点排序后分为两半,前半部分和后半部分按顺序连边即可另数量最大化,1 -> 5,2 -> 6, 3 -> 7····顺时针

code:

pii p[N];
int idx;

bool sk[N];
vector<int> v;


bool check(pii a, pii b) {
    if(a.first < b.first && a.second < b.second && b.first < a.second) return 1;
    if(b.first < a.first && b.second < a.second && a.first < b.second) return 1;
    return 0;
}

void solve(){
    int n, k;
    cin >> n >> k;
    idx = 0;
    memset(sk,0,sizeof sk);
    v.clear();
    for(int i = 1;i <= k;i ++) {
        int a,b;
        cin >> a >> b;
        if(a > b) swap(a,b);
        sk[a] = sk[b] = 1;
        p[++ idx] = {a,b};
    }
    for(int i = 1;i <= n * 2;i ++) {
        if(!sk[i]) v.push_back(i);
    }
    int len = v.size();
    for(int i = 0;i < len / 2;i ++) {
        p[++ idx] = {v[i], v[i + len / 2]};
    }
    int ans = 0;
    for(int i = 1;i < idx;i ++) {
        for(int j = i + 1;j <= idx;j ++) {
            // cout << p[i].first << ' ' << p[i].second << ' ' << p[j].first << ' ' << p[j].second << endl;
            if(check(p[i],p[j])) ans ++;
        }
    }
    cout << ans << endl;
}

D. Array Differentiation

  • 题意

给出一个序列(a_i), 要求你是否能构造出另一个序列(b_i), 满足任意(a_i = b_j - b_k),(1 <= i <= n, 1 <= j,k <= n).

  • 思路
  1. 首先,我们可以很简单的证明序列不能是升序或降序的。
  2. 其次,如果本题b的长度如果是n + 1个,那么随便填就行了,两两生成一个即可,所以我们需要思考可以怎么通过k个b[i],满足k个a[i],然后其他n - k个随便填就行了。
  3. 然后,可以发现, 如满足(a_i + a_j == a_k + a_d)类似的东西,对于b的求解就多了一个等式,那么就可以通过求解来满足:
    A: a b c d
    B: x1 x2 x3 x4
    首先,令x1 = a, x2 = -(d - a),x4 = 0
    那么, x1 - x2 = d, x1 - x4 = a,
    然后令x3 = -(b + (d - a)), 那么 x2 - x3 = c;
    然后a,c,d都出来了,通过等式对x1,x2,x3,x4进行运算不就出来了。

code:

const int N = 11;

set<int> t;
int a[N];

void solve(){
    int n;
    t.clear();
    cin >> n;
    for(int i = 1;i <= n;i ++) {
        cin >> a[i];
    }
    for(int i = 0;i < (1 << n);i ++) {
        int res = 0;
        for(int j = n - 1;j >= 0;j --) {
            if(i >> j & 1) res += a[j + 1];
        }
        if(t.count(res)) {
            cout << "YES" << endl;
            return;
        }
        t.insert(res);
    }
    cout << "NO" << endl;
}

F. Telepanting

  • 题意

一只蚂蚁从位置0走到位置(x_n + 1), 途中有n个传送阵,(op_i)表示是否激活
(op_i = 1)则激活,蚂蚁传送到(y_i)的位置上去
否则,激活这个传送
题目满足((x_i > x_j (n >= i > j >= 1)))

  • 思路

dp+二分预处理即可
首先,蚂蚁在走的下标之前的传送门,一定是都激活的
f[i]记录蚂蚁当前传送阵且激活的情况需要多走的路程

  1. 若往回走不需要经过传送门,之间减去两端(x_i - y_i)即可
  2. 否则,就多加一层前缀即可
    sum[i]记录f[i]前缀和
    忘了mod就等着wa吧

code:

const int N = 200100;
const int mod = 998244353;
int f[N];
int u[N],v[N],op[N];
int sum[N];
void solve(){
    int n;
    cin >> n;
    int now = 0;
    for(int i = 1;i <= n;i ++) {
        cin >> u[i] >> v[i] >> op[i];
        int l = 1,r = i;
        while(l < r) {
            int mid = l + r >> 1;
            if(v[i] <= u[mid]) r = mid;
            else l = mid + 1;
        }
        if(r == i)
        f[i] = (u[i] - v[i]);
        else 
        f[i] = (u[i] - v[i]) + (sum[i - 1] - sum[r - 1] + mod * 3) % mod; // 不mod就等着wa吧
        f[i] %= mod;
        sum[i] = (f[i] + sum[i - 1]) % mod;
        now = u[i];
    }
    int ans = u[n] + 1;
    for(int i = 1;i <= n;i ++) {
        if(op[i]) {
            ans += f[i];
            ans %= mod;
        }
    }
    cout << ans % mod << endl;
}

原文地址:https://www.cnblogs.com/darker-wxl/p/15068775.html