zoukankan      html  css  js  c++  java
  • Codeforces Round #702 (Div. 3) A B C D E F G

    比赛链接

    A - Dense Array

    定义一个数组是好的当且仅当相邻两个数较大的除以较小的<=2时成立。问给定一个数组,最少需要插入多少个数可以 s.t. 数组变成好的。

    Solution

    直接按照要求模拟

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 10;
    int arr[maxn];
    int cal(int x, int y)
    {
        if (x > y)
            swap(x, y);
        int ans = 0;
        while(true)
        {
            if (x * 2 >= y)
                break;
            x <<= 1;
            ans++;
        }
        return ans;
    }
    
    void solve()
    {
        int n;
        scanf("%d", &n);
        int ans = 0;
        for (int i = 1; i <= n; ++ i)
        {
            scanf("%d", &arr[i]);
            if(i > 1)
            {
                ans += cal(arr[i - 1], arr[i]);
            }
        }
        printf("%d
    ", ans);
    }
    
    int main()
    {
        int t = 1;
        scanf("%d", &t);
        while(t--)
        {
            solve();
        }
    }

    B - Balanced Remainders

    给定一个数组,所有值取模3。每次可以给一个数+1,算一次操作。问最少多少次操作可以 s.t. 取模后数组中0 1 2的数量一致

    Solution

    想象成一个环状的推箱子。最多推两次(猜的,但我写的是while(true))就可以全部推平了

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn = 3e4 + 10;
    int arr[maxn];
    void solve()
    {
        int n;
        scanf("%d", &n);
        int a[5];
        memset(a, 0, sizeof a);
        for (int i = 1; i <= n; ++ i)
        {
            scanf("%d", &arr[i]);
            a[arr[i] % 3]++;
        }
        int cnt = n / 3;
        if(a[0] == cnt && a[1] == cnt && a[2] == cnt)
        {
            printf("0
    ");
            return;
        }
    
        int xx = 0;
        int ans = 0;
        while(true)
        {
            bool flag = false;
            for (int i = 0; i < 3; ++ i)
            {
                if(a[i] > cnt)
                {
                    flag = true;
                    a[(i + 1) % 3] += a[i] - cnt;
                    ans += a[i] - cnt;
                    a[i] = cnt;
                }
            }
            if(!flag)
                break;
        }
        printf("%d
    ", ans);
        
    }
    int main()
    {
        int t = 1;
        scanf("%d", &t);
        while(t --)
        {
            solve();
        }
        return 0;
    }

    C - Sum of Cubes

    问一个数可否由两个正整数的三次方相加得到。

    Solution

    看到数据范围。枚举 i 即可,判断是否存在 j 即可。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    constexpr int maxn = 1e5 + 10;
    bool check(ll xx)
    {
        ll xll = 1, xrr = min(xx,10000*1ll);
        ll ans = -1;
        while(xll <= xrr)
        {
            ll mid = xll + xrr >> 1;
            if (mid * mid * mid < xx)
            {
                xll = mid + 1;
            }
            else
            {
                xrr = mid - 1;
                ans = mid;
            }
        }
        return ans * ans * ans == xx;
    }
    void solve()
    {
        ll n;
        scanf("%lld", &n); 
        for (ll i = 1; i <= n; ++ i)
        {
            if (i * i * i > n)
            {
                break;
            }
            ll xxxx = n - i * i * i;
            if(check(xxxx)) 
            {
                printf("YES
    ");
                return; 
            }
        }
        printf("NO
    ");
        return;
    }
    int main()
    {
        int t = 1;
        scanf("%d", &t);
        while(t --)
        {
            solve();
        }
        return 0;
    }

    D - Pythagorean Triples

    给定一个全排列,要求转换成二叉树。选当前序列最大值作为根,左侧最大值作为左子树,右侧最大值作为右子树。递归。

    Solution

    生成方法是递归,做法也是。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e2 + 10;
    int dep[maxn], arr[maxn];
    void dfs(int ll, int rr, int dd)
    {
        if(ll > rr)
            return;
    
        int MAX = -1;
        int pos = -1;
        for (int i = ll; i <= rr; ++ i)
        {
            if (MAX < arr[i])
            {
                MAX = arr[i];
                pos = i;
            }
        }
    
        dep[pos] = dd;
        dfs(ll, pos - 1, dd + 1);
        dfs(pos + 1, rr, dd + 1);
    }
    
    
    void solve()
    {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++ i)
        {
            scanf("%d", &arr[i]);
        }
        dfs(1, n, 0);
    
        for (int i = 1; i <= n; ++ i)
        {
            printf("%d%c", dep[i], " 
    "[i == n]);
        }
    }
    int main()
    {
        int t = 1;
        scanf("%d", &t);
        while(t --)
        {
            solve();
        }
        return 0;
    }

    E - Accidental Victory

    有n个人。每个人有初始分数ai,一共会发生n-1(每个人都会打2场比赛)场比赛。如果分数相同那么会随机判定一个人获胜。获胜方可以获得败方的所有分数。最后还有分数的人获胜。问有哪些人可能获胜。

    Solution

    分数从小到大排序,做个前缀和。如果当前前缀和<下一个位置的分数,那么从当前位置向前所有的人都不可能获胜。找到最后这样一个位置即可。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn = 2e5 + 10;
    int arr[maxn], nums[maxn];
    struct PERSON
    {
        int id, mon, xx;
    } person[maxn];
    bool cmp(PERSON x, PERSON y)
    {
        return x.mon < y.mon;
    }
    void solve()
    {
        int n;
        scanf("%lld", &n);
        for (int i = 1; i <= n; ++ i)
        {
            scanf("%lld", &person[i].mon);
            person[i].id = i;
            person[i].xx = 1;
        }
    
        sort(person + 1, person + 1 + n, cmp);
        set<int> ans;
        int xxx = 0;
        int last = 1;
        for (int i = 1; i <= n; ++ i)
        {
            if(i != 1)
            {
                if(xxx < person[i].mon)
                {
                    last = i;
                }
            }
            xxx += person[i].mon;
        }
        for (int i = last; i <= n; ++i)
            ans.insert(person[i].id);
        
        printf("%lld
    ", (int)ans.size());
        for(auto xxx : ans)
            printf("%lld ", xxx);
        puts("");
    }
    signed main()
    {
        int t = 1;
        scanf("%d", &t);
        while(t --)
        {
            solve();
        }
    }

    F - Equalize the Array

    定义一个数组是漂亮的当且仅当数组中所有相同的数出现的次数等于一个常数C或者等于0。问最少删掉多少个数才能 s.t. 数组是一个漂亮的数组。

    Solution

    离散化之后枚举最终结果数组的常数C,然后统计需要删除的数取min即可。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 10;
    int arr[maxn], brr[maxn];
    void solve()
    {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++ i)
            scanf("%d", &arr[i]);
        sort(arr + 1, arr + 1 + n);
        int index = 0;
        for (int i = 1; i <= n; ++ i)
        {
            if(i == 1)
            {
                brr[++index] = 1;
            }
            else
            {
                if(arr[i] != arr[i-1])
                    brr[++index] = 1;
                else
                    brr[index]++;
            }
        }
        int MIN = INT_MAX;
        sort(brr + 1, brr + 1 + index);
        for (int i = 1; i <= index;  ++ i)
        {
            MIN = min(MIN, n - brr[i] * (index - i + 1));
        }
        printf("%d
    ", MIN);
    }
    int main()
    {
        int t = 1;
        scanf("%d", &t);
        while(t --)
        {
            solve();
        }
        return 0;
    }

    G - Old Floppy Drive

    给定一个循环数组和X,从第一位开始累加,直到Sum >= X为止,问需要累加多少次或者永远不能达到

    Solution

    pref数组定义成前缀和数组。总和为Sum。Max代表pref中的最大值

    如果 X > MAX && Sum <= 0,显然无解

    其他情况都有解。 对于给定 X,总共需要跑 t1 = (X - Max + Sum - 1)/ Sum次,带来的贡献等于 t2 = t1 * Sum

    那么我们还需要至少有 t3 = X - t2的贡献。

    显然如果 pref[i-1] >= pref[i],那么pref[i]就是一个无效点,我们就可以维护出一个新的前缀和数组pref',这个数组里的值是严格递增的,这样我们就可以二分找到第一个大于等于t3的贡献点以及对应位置aa。

    于是我们得出答案为 t1 * n + aa。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 10;
    #define ll long long
    void solve()
    {
        vector<ll> pref;
        vector<int> ind;
        int n, m;
        ll Sum = 0;
        scanf("%d %d", &n, &m);
        ll MAX = -1;
        ll temp;
        for (int i = 1; i <= n; ++ i)
        {
            scanf("%lld", &temp);
            Sum += temp;
            if(pref.empty() || Sum > pref.back())
            {
                pref.push_back(Sum);
                ind.push_back(i-1);
            }
        }
    
        while (m--)
        {
            ll x;
            scanf("%lld", &x);
            if (x > pref.back() && Sum <= 0)
            {
                printf("-1 ");
                continue;
            }
            ll ans = 0;
            if (pref.back() < x)
            {
                ans = (x - pref.back() + Sum - 1) / Sum;
            }
            x -= ans * Sum;
            printf("%lld ", ans * n + ind[lower_bound(pref.begin(), pref.end(), x) - pref.begin()]);
        }
        puts("");
    
    }
    
    int main()
    {
        int t = 1;
        scanf("%d", &t);
        while(t --)
        {
            solve();
        }
        return 0;
    }
  • 相关阅读:
    Android笔记之添加退出确认对话框
    Android笔记之menu与ActionBar使用
    Android学习笔记之File存储(sd卡)
    cron 在线 表达式
    springboot
    mybatis 查询标签
    div display 常用属性
    css height VS min-height
    struts标签 解析html标签
    CSS 后代选择器
  • 原文地址:https://www.cnblogs.com/wifePI/p/14407708.html
Copyright © 2011-2022 走看看