zoukankan      html  css  js  c++  java
  • Codeforces Round #636 (Div. 3)

    题目传送门

    A - Candies

    题目大意:找到一个x ,存在k>1,使x + 2x + 4x + ⋯ + 2^(k−1)x = n。

    即找到x,k满足这个式子:(2^k-1)*x = n,可以枚举k 判断(2^k-1)|n

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    int main()
    {
        int t;
        cin >> t;
        ll n;
        while (t--)
        {
            cin >> n;
            for (ll k = 2; (1 << k) - 1 <= n; k++)
                if (n % ((1 << k) - 1) == 0)
                {
                    cout << n / ((1 << k) - 1) << endl;
                    break;
                }
        }
    }
    View Code

    B. Balanced Array

    题目大意,给一个偶数n,构造数列a满足:

    1.前n/2个数为偶数

    2.后n/2个数为奇数

    3.所有数不相同,大于零

    4.前n/2个数的和等于后n/2个数

     

    因为左右部分的和相同,奇数部分的个数为偶数,因为和为偶数,所以n%4!=0则不可构造,

    当n%4==0时,按照 2, 4, …, n-2, n,  1, 3, …, n-3, n+1, n+3, …, n+1  奇数中间跳一个值

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    int main()
    {
        int t, n;
        cin >> t;
        while (t--)
        {
            cin >> n;
            if (n % 4)
                puts("NO");
            else
            {
                puts("YES");
                for (int i = 2; i <= n; i += 2)
                    cout << i << " ";
                for (int i = 1; i <= n + 1; i += 2)
                    if (i != n / 2 + 1)
                        cout << i << " ";
                cout << endl;
            }
        }
    }
    View Code

    C. Alternating Subsequence

    题目大意,给一个序列a,最大化长度最大的正负数交错排列的子序列的和。

    长度最大即连续的正数或负数之中必须要选一个,那么直接选最大的那个

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    int main()
    {
        int t, n;
        ll ans, a, tmp;
        cin >> t;
        while (t--)
        {
            cin >> n;
            ans = 0;
            tmp = 0;
            rep(i, 1, n)
            {
                cin >> a;
                if (tmp * a > 0)
                    tmp = max(tmp, a);
                else
                {
                    ans += tmp;
                    tmp = a;
                }
            }
            cout << ans + tmp << endl;
        }
    }
    View Code

    D. Constant Palindrome Sum

    题目大意,给一个长度为n的序列a,将a中的值改为中[1,k]任意一个数,满足i∈[1,n/2] ai+an-i+1 = x值相等,求最小的修改次数。

    可以发现对于每一对数,修改次数为0,1,2,由x决定

        [ 2, min(a[i], a[n-i+1]) ]                             2次

        [ min(a[i], a[n-i+1])+1, a[i]+a[n-i+1]-1 ]     1次

        a[i]+a[n-i+1]                                              0次

        [ a[i]+a[n-i+1]+1,max(a[i], a[n-i+1])+k ]     1次

        [ max(a[i], a[n-i+1])+k+1, 2*k ]                  2次

    枚举x∈[2,k * 2],遍历a数组,求得最小的修改次数,复杂度O(nk),显然不行

    因为修改次数区间是连续的,可以用线段树或者树状数组来维护x∈[2,k * 2]的修改次数

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    int n, k, ans, a[200010];
    
    int c[400010];
    int lowbit(int x)
    {
        return x & (-x);
    }
    
    void update(int x, int d)
    {
        while (x <= 2 * k + 1)
        {
            c[x] += d;
            x += lowbit(x);
        }
    }
    
    int getsum(int x)
    {
        int tmp = 0;
        while (x)
        {
            tmp += c[x];
            x -= lowbit(x);
        }
        return tmp;
    }
    
    int main()
    {
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        int t;
        cin >> t;
        while (t--)
        {
            cin >> n >> k;
            rep(i, 1, n) cin >> a[i];
            rep(i, 1, k * 2 + 1) c[i] = 0;
            rep(i, 1, n / 2)
            {
                update(2, 2);
                update(min(a[i], a[n - i + 1]) + 1, -1);
                update(a[i] + a[n - i + 1], -1);
                update(a[i] + a[n - i + 1] + 1, 1);
                update(max(a[i], a[n - i + 1]) + k + 1, 1);
                update(2 * k + 1, -2);
            }
            ans = n;
            rep(i, 2, 2 * k)
                ans = min(ans, getsum(i));
            cout << ans << endl;
        }
    }
    View Code

    E. Weights Distributing

    题目大意,给定无向无权图,给图加权值,使a->b,b->c代价最小

    设a->b经过x,如果b->c经过x,那么一定是延a->x->b的方向返回至x,就可以理解成a->x->b->x->c

    枚举x,求dis(a,x) + 2*dis(b,x) + dis(c,x)最小值,中间求个前缀和就行了

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i, a, b) for (register int i = a; i <= b; i++)
    
    int n, m, a, b, c;
    ll p[200010], ans;
    
    struct node
    {
        int to, next;
    } e[400010];
    int id = 0, head[200010];
    int disa[200010], disb[200010], disc[200010];
    void add(int x, int y)
    {
        id++;
        e[id].to = y;
        e[id].next = head[x];
        head[x] = id;
    }
    int main()
    {
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        int t, u, v;
        cin >> t;
        while (t--)
        {
            id = 0;
            memset(head, 0, sizeof(head));
            cin >> n >> m >> a >> b >> c;
            rep(i, 1, m) cin >> p[i];
            sort(p + 1, p + m + 1);
            rep(i, 1, m) p[i] += p[i - 1];
            rep(i, 1, m)
            {
                cin >> u >> v;
                add(u, v);
                add(v, u);
            }
            rep(i, 1, n) disa[i] = disb[i] = disc[i] = -1;
            queue<int> q;
            q.push(a);
            disa[a] = 0;
            while (!q.empty())
            {
                int u = q.front();
                q.pop();
                for (int i = head[u]; i; i = e[i].next)
                    if (disa[e[i].to] == -1)
                    {
                        disa[e[i].to] = disa[u] + 1;
                        q.push(e[i].to);
                    }
            }
            q.push(b);
            disb[b] = 0;
            while (!q.empty())
            {
                int u = q.front();
                q.pop();
                for (int i = head[u]; i; i = e[i].next)
                    if (disb[e[i].to] == -1)
                    {
                        disb[e[i].to] = disb[u] + 1;
                        q.push(e[i].to);
                    }
            }
            q.push(c);
            disc[c] = 0;
            while (!q.empty())
            {
                int u = q.front();
                q.pop();
                for (int i = head[u]; i; i = e[i].next)
                    if (disc[e[i].to] == -1)
                    {
                        disc[e[i].to] = disc[u] + 1;
                        q.push(e[i].to);
                    }
            }
            ans = p[m] * 2;
            rep(i, 1, n) if (disa[i] + disb[i] + disc[i] <= m) ans = min(ans, p[disb[i]] + p[disa[i] + disb[i] + disc[i]]);
            cout << ans << endl;
        }
    }
    View Code
  • 相关阅读:
    Linux之redis-cluster(集群配置)
    MariaDB主从复制,redis发布订阅,持久化,以及主从同步
    Vue之添加全局变量
    Linux之nginx入门
    Linux中python3,django,redis以及mariab的安装
    Linux系统优化及基础命令
    linux基本命令
    Linux常用命令大全
    Flask之项目配置,目录构建,闪现
    C语言II博客作业04
  • 原文地址:https://www.cnblogs.com/likunhong/p/12749529.html
Copyright © 2011-2022 走看看