zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 098

    传送门

    C - Attention

    前后缀搞一搞即可。

    Code
    #include <bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    //#define Local
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int N = 3e5 + 5;
    
    int n;
    char s[N];
    int pre[N], suf[N];
    
    void run() {
        cin >> s + 1;
        for(int i = 1; i <= n; i++) {
            pre[i] = pre[i - 1];
            if(s[i] == 'W') ++pre[i];
        }
        suf[n + 1] = 0;
        for(int i = n; i >= 1; i--) {
            suf[i] = suf[i + 1];
            if(s[i] == 'E') ++suf[i];
        }
        int ans = n + 1;
        for(int i = 1; i <= n; i++) {
            ans = min(ans, pre[i - 1] + suf[i + 1]);
        }
        cout << ans << '
    ';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
    #ifdef Local
        freopen("../input.in", "r", stdin);
        freopen("../output.out", "w", stdout);
    #endif
        while(cin >> n) run();
        return 0;
    }
    
    

    D - Xor Sum 2

    题意:
    给出一个长度为(n)的序列(a),现在问有多少区间([l,r]),满足:

    [a_l xor a_{l+1} xor cdots xor x_r=a_l+a_{l+1}+cdots+a_r ]

    思路:
    注意这样一个性质:(a_i xor a_jleq a_i+a_j)
    所以一旦一个区间不满足条件过后,更大的区间也不满足了;一个区间满足条件,更小的区间也满足。
    所以直接双指针搞搞就行。

    Code
    #include <bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    //#define Local
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int N = 2e5 + 5;
    
    int n;
    int a[N];
    
    void run() {
        for(int i = 1; i <= n; i++) cin >> a[i];
        int j = 0;
        ll sum1 = 0, sum2 = 0;
        ll ans = 0;
        for(int i = 1; i <= n; i++) {
            while(j + 1 <= n) {
                if(sum1 + a[j + 1] == (sum2 ^ a[j + 1])) {
                    sum1 += a[++j], sum2 ^= a[j];
                }
                else break;
            }
            ans += j - i + 1;
            sum1 -= a[i]; sum2 ^= a[i];
        }
        cout << ans << '
    ';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
    #ifdef Local
        freopen("../input.in", "r", stdin);
        freopen("../output.out", "w", stdout);
    #endif
        while(cin >> n) run();
        return 0;
    }
    
    

    E - Range Minimum Queries

    题意:
    给出一个长度为(n)的序列(a),现在执行(q)次操作,每次选择一段长度为(k)的区间,删除一个最小的数(如果有多个,可任意删除一个)。
    最后问在所有删除的数中,相差最小为多少。

    思路:

    • 很容易想到二分差值,然后枚举下界,这样就知道了上下界。
    • 因为每次必须选择最小的一个数,所以所有大于等于下界的数构成了一个个可执行区间(因为若区间中含小于的数那肯定不合法),每次在这些区间里面贪心选就行。

    详见代码:

    Code
    #include <bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    //#define Local
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int N = 2005;
    
    int n, k, q;
    int a[N];
    
    bool chk(int x) {
        for(int i = 1; i <= n; i++) {
            int Min = a[i];
            int res = 0;
            for(int l = 1, r; l <= n; l = r) {
                r = l;
                if(a[l] < Min) {
                    ++r; continue;
                }
                int cnt = 0;
                while(r <= n && a[r] >= Min) {
                    if(a[r] <= Min + x) ++cnt;
                    ++r;
                }
                if(r - l >= k) res += min(r - l + 1 - k, cnt);
            }
            if(res >= q) return true;
        }
        return false;
    }
    
    void run() {
        for(int i = 1; i <= n; i++) cin >> a[i];
        int l = 0, r = 1e9 + 1, mid;
        while(l < r) {
            mid = (l + r) >> 1;
            if(chk(mid)) r = mid;
            else l = mid + 1;
        }
        cout << l << '
    ';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
    #ifdef Local
        freopen("../input.in", "r", stdin);
        freopen("../output.out", "w", stdout);
    #endif
        while(cin >> n >> k >> q) run();
        return 0;
    }
    
    

    F - Donation

    题意:
    给出一个无向图,选定一个起点,一开始有(W)元,之后可以选择走向相邻一个节点或者给当前结点捐赠(b_i)元,若走向一个结点至少得有(a_i)元才行。
    现在确定一个最小的(W)以及一个起点,使得最终能够顺利捐赠成功每个点。

    思路:
    还有点没想清楚,先埋个坑。

  • 相关阅读:
    rabbitmq报错:not_a_dets_file,"/var/lib/rabbitmq/mnesia/rabbit@Sfabrici-Demo01/recovery.dets"的解决办法
    ubuntu18上关闭默认的防火墙
    《GCD宣言》全文
    springboot日志配置
    springboot打jar包【我】
    MongoDB 4.2 用户管理
    【短道速滑四】Halcon的texture_laws算子自我研究
    Android集合之SparseArray、ArrayMap详解
    浅析微信支付:下载对账单和资金账单
    学习如修行
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11656203.html
Copyright © 2011-2022 走看看