zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 77 (Rated for Div. 2)

    传送门

    感觉最近写代码的状态有点迷...还好这次最后两分钟过了D,不然就掉分了QAQ。

    A. Heating

    签到。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/11/27 21:53:49
     */
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    void run(){
        int c, sum; cin >> c >> sum;
        int d = max(sum / c, 1), r = sum % c;
        int ans = 0;
        if(r == 0) {
            ans = d * d * c;
        } else {
            for(int i = 1;; i++) {
                ans += d * d;
                --c; sum -= d;
                if(sum == 0) break;
                if(sum % c == 0) {
                    d = sum / c;
                    ans += c * d * d;
                    break;
                }
            }   
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    B. Obtain Two Zeroes

    分情况,列一下方程找关系即可。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/11/27 22:03:54
     */
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    void run(){
        int x, y; cin >> x >> y;
        if(x > y) swap(x, y);
        int f = 0;
        if(2 * y - x >= 0 && (2 * y - x) % 3 == 0) {
            int t = (2 * y - x) / 3;
            if(x >= t && y >= 2 * t) f = 1;
        }
        if(2 * x - y >= 0 && (2 * x - y) % 3 == 0) {
            int t = (2 * x - y) / 3;
            if(x >= 2 * t && y >= t) f = 1;
        }
        if(f) cout << "YES" << '
    ';
        else cout << "NO" << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    C. Infinite Fence

    题意:
    现在有无穷多个砖块排成一行,现在从(0)开始,每(r)个涂一种颜色,每(b)个涂一种颜色。形式化地说,就是(0,r,2r,cdots)以及(0,b,2r,cdots)这些砖块各涂一种颜色。
    如果存在一个位置(x),满足(r|x,b|x),那么(x)这个位置可以选择一种颜色去涂。
    现在有多组询问,每组询问回答是否有颜色相同且连续的多个砖块,其个数小于(k)

    思路:

    • 显然我们只需要考虑(0)~(lcm(r,b))即可。
    • 不妨设(r<b),那么(q=b\% r),也就相当于(b)每涂一次,只会在长度为(r)的区间中前进(q)(不考虑中间经过的完整的区间)。
    • 显然,连续的砖块个数最多的情况,就是存在(x,y),使得(|xr-yb|)最小,也就是说某一次涂完(b)之后,这时的位置离(r)的倍数最近,那么下一次涂就可以尽可能远。
    • (p=r\% q),之后即可确定出起点,然后找到终点,统计一下中间个数即可。

    好像这个有个什么结论,不过这种思路也不是很复杂~
    细节见代码:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/11/27 22:33:59
     */
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    ll r, b, k;
     
    void run(){
        cin >> r >> b >> k;
        if(r > b) swap(r, b);
        if(b % r == 0) {
            int d = b / r - 1;
            if(d >= k) {
                cout << "REBEL" << '
    ';   
            } else cout << "OBEY" << '
    ';
        } else {
            int q = b % r;
            int p = r % q;
            ll s;
            if(p == 0) {
                s = r - q;
            } else s = r - p;
            ll e = s + b;
            int cnt = e / r - (s - 1) / r;
            if(e % r == 0) --cnt;
            if(cnt >= k) cout << "REBEL" << '
    ';
            else cout << "OBEY" << '
    ';
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    D. A Game with Traps

    题意:
    现在有一条长度为(n)的战线,你要带领一些士兵从(0)(n+1)
    中间的某些位置可能存在陷阱,其位置为(l_i),深度为(d_i)。某些士兵有其敏捷度(a_i),若(a_i<d_i),他就会阵亡。
    但是你,不会受到陷阱的影响,相反若对于某个(l_i),走到(r_i),能够拆除这个陷阱。
    你当前可以进行如下操作:

    • 花费一秒的时间,独立从(x)走到(x-1)(x+1)
    • 花费一秒的时间,带领士兵从(x)走到(x+1),此时你也要在(x+1)
    • 进行拆除陷阱的操作,不消耗时间。

    问在(t)秒内,能够带领最多多少的士兵走到(n+1)的位置。

    思路:
    这个题题意稍微有点绕,但是思路不是很难。
    很显然的我们可以二分答案。
    然后直接模拟这个过程,贪心往前走就行。关键就是通过一个变量(rbound)来记录你走到右边的最远位置,因为拆除陷阱是,肯定是能拆的一次性拆完。我们利用(rbound)来统计贡献就行。
    细节见代码:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/11/27 22:56:01
     */
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e5 + 5;
     
    int m, n, k, t;
    int a[N];
    vector <pii> v[N];
     
    bool chk(int x) {
        ll c = 0;
        int rb = 0;
        int low = a[m - x + 1];
        for(int i = 0; i <= n; i++) {
            rb = max(rb, i);
            if(sz(v[i + 1]) > 0) {
                for(int j = 0; j < sz(v[i + 1]); j++) {
                    pii now = v[i + 1][j];
                    if(now.fi <= low || now.se <= rb) {} 
                    else {
                        c += 2 * (ll)(now.se - rb);
                        rb = now.se; 
                    }
                }
            }
            if(++c > (ll)t) return false;
        }
        return true;
    }
     
    void run(){
        for(int i = 1; i <= m; i++) cin >> a[i];
        sort(a + 1, a + m + 1);
        for(int i = 1; i <= k; i++) {
            int l, r, d; cin >> l >> r >> d;
            v[l].push_back(MP(d, r));   
        }
        for(int i = 1; i <= n; i++) if(sz(v[i])) {
            sort(v[i].begin(), v[i].end(), [&](pii A, pii B) {
                 if(A.fi != B.fi) return A.fi > B.fi;
                 else return A.se > B.se; });   
        }
        int l = 1, r = m + 1, mid;
        while(l < r) {
            mid = (l + r) >> 1;
            if(chk(mid)) l = mid + 1;
            else r = mid;   
        }
        cout << l - 1 << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        while(cin >> m >> n >> k >> t) run();
        return 0;
    }
    

    E. Tournament

    题意:
    现在有(n)个选手参加比赛,你的朋友也在里面。
    每个选手有一个力量值(i),显然在两两的比赛中力量值大的会胜出。
    比赛的规则就是每一轮两两比赛,最后胜者进入下一轮,然后重复此过程直至某一人胜出。
    你的朋友很可能GG,但是你可以贿赂那些人,贿赂的代价为(a_i)
    问最后使得你的朋友胜出的最小代价是多少。

    思路:
    感觉很有意思的一个题,也不是很好想(菜就对了)。
    显然如果我们倒着来考虑整个比赛的过程,那么会形成一颗满二叉树。
    第二层有两个结点,一个结点是你的朋友,另一个结点是你的对手。那么可以当作你的对手在之前KO了(frac{n}{2})个人,而此时你必须贿赂你的对手来获得胜利(如果他力量比你低,那代价为(0),因为此时的对手肯定是最后一个人)。
    同理,之后到了第三层,你朋友的对手会打败(frac{n}{4})个人...然后依次类推。
    之后有一个引理:

    • 若当前是第(x)层,那么你会遇到(x-1)个对手,所有的对手会打败(tot=frac{n}{2}+cdots+frac{n}{2^{x-1}})个人。那么,下一轮你能够从后面(tot+1)个位置任选一个人(当然不能选过)当作你的对手。

    证明的话就是对于每一个规模的问题,你肯定要贿赂当前的最强者。又因为可以任意安排策略,所以你一定能够在后面(力量值比较大的部分)选择你的对手。同时每一个对手又能不断增加击败人数...然后yy一下就有了。

    如果能将树的思路和这个引理想到并且想清楚了。那么用一个小根堆模拟一下就行。
    还是挺巧妙的hhh思路转换一下就出来了。
    代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/11/28 22:15:03
     */
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <iomanip>
    #include <queue>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e6 + 5;
     
    int n;
    int a[N];
     
    void run(){
        for(int i = 1; i <= n; i++) cin >> a[i];
        reverse(a + 1, a + n + 1);
        priority_queue <int, vector<int>, greater<int> > q;
        int now = 1;
        q.push(a[now++]);
        ll ans = 0;
        int win = n / 2;
        while(!q.empty()) {
            int cur = q.top(); q.pop();
            if(cur == -1) break;
            ans += cur;
            for(int i = 1; i <= win; i++) q.push(a[now++]);
            win /= 2;
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        while(cin >> n) run();
        return 0;
    }
    
  • 相关阅读:
    PHP中的闭包详解
    PHPDoc 学习记录
    php中注释有关内容
    命名空间 转
    php命名空间学习笔记。
    php命名空间详解
    命名空间
    php作用域限定符
    nginx负载均衡
    naginx安装入门
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11955646.html
Copyright © 2011-2022 走看看