zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    平衡树之splay BZOJ3224 普通平衡树
    线段树 洛谷P1531 I Hate It
    倍增LCA code[vs]1036商务旅行
    线段树 hdu1698 Just a Hook
    猥琐的暴搜 NOIP2011 Mayan游戏
    [BZOJ2301][HAOI2011]Problem b
    [BZOJ1101][POI2007]Zap
    [BZOJ1100][POI2007]对称轴osi
    [BZOJ3167][Heoi2013]Sao
    [BZOJ3039]玉蟾宫
  • 原文地址:https://www.cnblogs.com/darker-wxl/p/15068775.html
Copyright © 2011-2022 走看看