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

    A - Equalize Prices Again

    题意:给n个商品,每个商品价格不同,要调整他们的价格,使得总价不下降且他们的价格相等,在此基础上最小化总价。

    题解:找超过原总价的最小的n的倍数。

    void test_case() {
        int n;
        scanf("%d", &n);
        ll sum = 0;
        for(int i = 1; i <= n; ++i) {
            ll tmp;
            scanf("%lld", &tmp);
            sum += tmp;
        }
        sum = (sum + n - 1) / n;
        printf("%lld
    ", sum);
    }
    

    B1 - Social Network (easy version)

    见下

    B2 - Social Network (hard version)

    题意:有个手机,屏幕能显示k个聊天窗口,已知n个人给你发消息的序列,求最终的聊天窗口。

    调整规则如下:

    1. 假如当前聊天窗口中有这个人,啥都不做,结束
    2. 否则,若窗口已满,去掉最底部的窗口
    3. 其他窗口下移,新的显示在顶部

    题解:看起来就是个队列,然后还要查队列里有没有某个元素,这个用个set就完事了。不过最后题目要从顶部到底部输出,所以一开始就用双端队列就很方便。

    set<int> s;
    deque<int> q;
     
    void test_case() {
        s.clear();
        int n, k;
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; ++i) {
            int id;
            scanf("%d", &id);
     
            if(s.count(id))
                continue;
            else {
                if(q.size() >= k) {
                    s.erase(q.front());
                    q.pop_front();
                }
                q.push_back(id);
                s.insert(id);
            }
        }
        printf("%d
    ", (int)q.size());
        while(q.size()) {
            printf("%d ", q.back());
            q.pop_back();
        }
        printf("
    ");
    }
    

    C - Pipes

    题意:有个两行的水管,水管只有两种形状,直的,或者拐角的。连接这些水管使得(1,0)的水可以流到(2,n+1)。

    题解:由于只有两行,所以每行结束必须往右流,直接dp即可。注意设置的时候不要在同层之间传递。

    char s[2][200005];
    bool dp[2][200005];
     
    void test_case() {
        int n;
        scanf("%d", &n);
        scanf("%s%s", s[0] + 1, s[1] + 1);
        for(int i = 1; i <= n; ++i)
            s[0][i] -= '0', s[1][i] -= '0';
        /*for(int i = 1; i <= n; ++i)
            putchar(s[0][i]);
        putchar('
    ');
        for(int i = 1; i <= n; ++i)
            putchar(s[1][i]);
        putchar('
    ');*/
        for(int i = 1; i <= n; ++i)
            dp[0][i] = dp[1][i] = 0;
        dp[0][0] = 1;
        dp[1][0] = 0;
        for(int i = 1; i <= n; ++i) {
            if(dp[0][i - 1] == 1 && s[0][i] <= 2)
                dp[0][i] = 1;
            if(dp[1][i - 1] == 1 && s[1][i] <= 2)
                dp[1][i] = 1;
            if(dp[0][i - 1] == 1 && s[0][i] >= 3 && s[1][i] >= 3)
                dp[1][i] = 1;
            if(dp[1][i - 1] == 1 && s[1][i] >= 3 && s[0][i] >= 3)
                dp[0][i] = 1;
        }
        /*for(int i = 0; i <= n; ++i)
            printf("%d", (int)dp[0][i]);
        putchar('
    ');
        for(int i = 0; i <= n; ++i)
            printf("%d", (int)dp[1][i]);
        putchar('
    ');*/
        if(dp[1][n])
            puts("YES");
        else
            puts("NO");
    }
    

    D - Distinct Characters Queries

    题意:给个只有小写拉丁字母的字符串,然后q次操作。

    操作1:把pos位置换成小写拉丁字母c。(pos一定在原串中)

    操作2:求[l,r]区间有多少种字母。

    题解:线段树

    struct SegmentTree {
    #define ls (o<<1)
    #define rs (o<<1|1)
        static const int MAXN = 200000;
        int a[MAXN + 5];
        int st[(MAXN << 2) + 5];
     
        void PushUp(int o) {
            st[o] = st[ls] | st[rs];
        }
     
        void Build(int o, int l, int r) {
            if(l == r)
                st[o] = a[l];
            else {
                int m = l + r >> 1;
                Build(ls, l, m);
                Build(rs, m + 1, r);
                PushUp(o);
            }
        }
     
        void Update(int o, int l, int r, int p, int v) {
            if(l == r) {
                st[o] = v;
                return;
            } else {
                int m = l + r >> 1;
                if(p <= m)
                    Update(ls, l, m, p, v);
                if(p >= m + 1)
                    Update(rs, m + 1, r, p, v);
                PushUp(o);
            }
        }
     
        int Query(int o, int l, int r, int ql, int qr) {
            if(ql <= l && r <= qr) {
                return st[o];
            } else {
                int m = l + r >> 1;
                int res = 0;
                if(ql <= m)
                    res = res | Query(ls, l, m, ql, qr);
                if(qr >= m + 1)
                    res = res | Query(rs, m + 1, r, ql, qr);
                return res;
            }
        }
    #undef ls
    #undef rs
    } st;
     
    char s[200005];
     
    void test_case() {
        scanf("%s", s + 1);
        int n = strlen(s + 1);
        for(int i = 1; i <= n; ++i)
            st.a[i] = 1 << (s[i] - 'a');
        st.Build(1, 1, n);
        /*for(int i = 1; i <= n; ++i)
            printf("%d ", st.Query(1, 1, n, i, i));
        putchar('
    ');*/
        int q;
        scanf("%d", &q);
        while(q--) {
            int op;
            scanf("%d", &op);
            if(op == 1) {
                int x;
                char ch[2];
                scanf("%d%s", &x, ch);
                st.Update(1, 1, n, x, 1 << (ch[0] - 'a'));
            } else {
                int l, r;
                scanf("%d%d", &l, &r);
                printf("%d
    ", __builtin_popcount((uint)st.Query(1, 1, n, l, r)));
            }
        }
    }
    

    *E - Special Permutations

    数字i在排列中的位置,总是(i-1)次i,1次1,n-i次i+1。相邻的两个排列最多改变了两个数的位置。

  • 相关阅读:
    线性表的各种基本操作
    malloc&&free的系统运行机制及其源代码的理解
    剪枝的定义&&hdu1010
    hdu 1045
    hdu2094 stl之set的应用
    关联式容器的总结
    STL之map容器的详解
    2018-2019 ACM-ICPC 焦作赛区 部分题解
    2018-2019 ACM-ICPC 沈阳赛区 K. Let the Flames Begin
    2018-2019 ACM-ICPC 徐州区域赛 部分题解
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12149376.html
Copyright © 2011-2022 走看看