zoukankan      html  css  js  c++  java
  • Codeforces 377

    简单说一下。

    A

      搜索出任意一个剩余细胞个数的联通块。剩下的填X。

    B

      二分加贪心加数据结构。

    /* 
     * Problem: 
     * Author: Shun Yao
     */
    
    #include <string.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <assert.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <math.h>
    #include <time.h>
    
    #include <map>
    #include <set>
    #include <list>
    #include <stack>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #include <bitset>
    #include <utility>
    #include <iomanip>
    #include <numeric>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    //using namespace std;
    
    const int MAXN = 100010, MAXM = 100010;
    
    int n, m, s, a[MAXM], ai[MAXM], b[MAXN], c[MAXN], bc[MAXN];
    
    bool cmpa(int x, int y) {
        return a[x] < a[y];
    }
    
    bool cmpb(int x, int y) {
        return b[x] < b[y];
    }
    
    class cmpc {
    public:
        bool operator () (int x, int y) {
            return c[x] > c[y];
        }
    } ;
    
    bool check(int x) {
        std::priority_queue<int, std::vector<int>, cmpc> pq;//小根堆
        int i, j = n, k = 0;
        for (i = m; i >= 1; i -= x) {
            while (j >= 1 && b[bc[j]] >= a[ai[i]]) {
                pq.push(bc[j]);
                --j;
            }
            if (pq.empty())
                return 0;
            k += c[pq.top()];
            pq.pop();
            if (k > s)
                return 0;
        }
        return 1;
    }
    
    void output(int x) {
        puts("YES");
        std::priority_queue<int, std::vector<int>, cmpc> pq;
        int i = m, j = n, k, ans[MAXM];
        while (i >= 1) {
            while (j >= 1 && b[bc[j]] >= a[ai[i]]) {
                pq.push(bc[j]);
                --j;
            }
            for (k = 1; k <= x && i >= 1; ++k, --i)
                ans[ai[i]] = pq.top();
            pq.pop();
        }
        for (i = 1; i <= m; ++i)
            printf("%d ", ans[i]);
    }
    
    int main(/*int argc, char **argv*/) {
        int i, l, r, mid;
        
        scanf("%d%d%d", &n, &m, &s);
        for (i = 1; i <= m; ++i) {
            scanf("%d", a + i);
            ai[i] = i;
        }
        for (i = 1; i <= n; ++i) {
            scanf("%d", b + i);
            bc[i] = i;
        }
        for (i = 1; i <= n; ++i)
            scanf("%d", c + i);
        std::sort(ai + 1, ai + m + 1, cmpa);
        std::sort(bc + 1, bc + n + 1, cmpb);
        if (!check(m))
            printf("NO");
        else {
            l = 1;
            r = m;
            while (l < r) {
                mid = (l + r) >> 1;
                if (check(mid))
                    r = mid;
                else
                    l = mid + 1;
            }
            output(r);
        }
        
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    

    C

      贪心,dp,位运算。

    /* 
     * Problem: C. Captains Mode
     * Author: Shun Yao
     */
    
    #include <string.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <assert.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <math.h>
    #include <time.h>
    
    #include <map>
    #include <set>
    #include <list>
    #include <stack>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #include <bitset>
    #include <utility>
    #include <iomanip>
    #include <numeric>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    //using namespace std;
    
    int n, m, a[111],  d[21], p[1048577], f[1048577];
    char c[21];
    
    int main(/*int argc, char **argv*/) {
        int i, j, x, y;
        
        scanf("%d", &n);
        for (i = 1; i <= n; ++i)
            scanf("%d", a + i);
        std::sort(a + 1, a + n + 1, std::greater<int>());
        scanf("%d", &n);
        for (i = 1; i <= n; ++i)
            scanf(" %c %d", c + i, d + i);
        m = (1 << n) - 1;
        p[0] = 0;
        for (i = 1; i <= m; ++i)
            p[i] = p[i >> 1] + (i & 1);
        f[m] = 0;
        for (i = m - 1; i >= 0; --i) {
            f[i] = d[x = p[i] + 1] == 2 ? INT_MAX : INT_MIN;
            for (j = 1; j <= n; ++j) {
                y = 1 << (j - 1);
                if (i & y || f[i ^ y] == INT_MAX || f[i ^ y] == INT_MIN)
                    continue;
                if (d[x] == 1) {
                    if (c[x] == 'p')
                        f[i] = std::max(f[i], f[i ^ y] + a[j]);
                    else
                        f[i] = std::max(f[i], f[i ^ y]);
                } else {
                    if (c[x] == 'p')
                        f[i] = std::min(f[i], f[i ^ y] - a[j]);
                    else
                        f[i] = std::min(f[i], f[i ^ y]);
                }
            }
        }
        printf("%d", f[0]);
        
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    

    D

      官方做法是把l,v,r看成平面上的矩形。用线段树求出重叠数最多的部分。

    E

      仔细分析一下,很明显是维护一个下凸,用单调栈即可。

      

  • 相关阅读:
    线段树
    2016.9.4
    使用CSS代码修改博客模板
    爬虫
    PHP初学[DAY2]
    2016.8.23
    一个自动设置游戏房间的脚本
    可逆矩阵生成
    #2284. 接水果(fruit)
    #3762. 有趣的数(number)
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3510026.html
Copyright © 2011-2022 走看看