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

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

  

posted @ 2014-01-08 07:50  hsuppr  阅读(236)  评论(0编辑  收藏  举报