zoukankan      html  css  js  c++  java
  • Codeforces Round 500 (Div 2) Solution

    Problem A Piles With Stones

    题目大意

      有若干堆石子排成一排。第一天科研人员记录了它们每一堆的数量。第二天科研人员又记录了这些石子的数量。晚上可能有非常多的游客来过。每个游客有三种可选操作:

    1. 不对石子做什么。
    2. 拿走一个石子
    3. 将一个石子移动到另一堆中。

      给定两天记录的数据问是否可能。

       直接判断第二天的数量是否小于等于第一天。

    Code

     1 /**
     2  * Codeforces
     3  * Problem#1013A
     4  * Accepted
     5  * Time: 31ms
     6  * Memory: 0k
     7  */ 
     8 #include <iostream>
     9 #include <cstdlib>
    10 #include <cstdio>
    11 using namespace std;
    12 typedef bool boolean;
    13 
    14 int n;
    15 int s1 = 0;
    16 
    17 inline void init() {
    18     scanf("%d", &n);
    19     for (int i = 1, x; i <= n; i++)
    20         scanf("%d", &x), s1 += x;
    21     for (int i = 1, x; i <= n; i++)
    22         scanf("%d", &x), s1 -= x;
    23     if (s1 < 0)
    24         puts("No");
    25     else
    26         puts("Yes");
    27 }
    28 
    29 int main() {
    30     init();
    31     return 0;
    32 }
    Problem A

    Problem B And

    题目大意

      给定$n$个数和$x$,将一个数按位与$x$算作一次操作,要求序列中至少有两个相同的数,问最少的操作数。无解输出-1.

       显然答案只可能是-1,0,1,2。

      第一种是无解。第二种不需要操作。第三种是一个数按位与x后与另一个数相同。最后一种是两个数与x后相同。

      每个数与x,然后用stl判一判。

    Code

     1 /**
     2  * Codeforces
     3  * Problem#1013B
     4  * Accepted
     5  * Time: 124ms
     6  * Memory: 4200k
     7  */ 
     8 #include <bits/stdc++.h>
     9 using namespace std;
    10 typedef bool boolean;
    11 
    12 const int N = 1e5 + 5;
    13 
    14 int n, x;
    15 int ar[N];
    16 map<int, int> sa;
    17 set<int> sb;
    18 
    19 inline void init() {
    20     scanf("%d%d", &n, &x);
    21     for (int i = 1, a; i <= n; i++) {
    22         scanf("%d", &a);
    23         ar[i] = a;
    24         if (sa.count(a)) {
    25             puts("0");
    26             exit(0);
    27         }
    28         sa[a] = i;
    29     }
    30 }
    31 
    32 int res = 3;
    33 inline void solve() {
    34     for (int i = 1; i <= n; i++) {
    35         int b = ar[i] & x;
    36         if (sb.count(b))
    37             res = min(res, 2);
    38         sb.insert(b);
    39         if (sa.count(b) && sa[b] != i)
    40             res = 1;
    41     }
    42     if (res == 3)
    43         puts("-1");
    44     else
    45         printf("%d", res);
    46 }
    47 
    48 int main() {
    49     init();
    50     solve();
    51     return 0;
    52 }
    Problem B

    Problem C Photo of The Sky

    题目大意

      有$2n$个数,要求分成元素个数相等的两组$X$和$Y$,且$left(max(X) - min(X) ight)left(max(Y) - min(Y) ight)$最小。问这个最小值。其中$min(X),max(X)$分别表示$X$中最小、最大的数。

       考虑两种情况:

    • 如果最大值和最小值在同一个集合内,那么设下的数一定是排序后连续的一段,否则我取这中间最小的和排它后面的$(n - 1)$可以更优。这一部分可以$O(n)$处理掉。
    • 如果最大值和最小值在不同集合内,那么我们要使最小值在的集合的最大值尽量小,最大值在的集合的最小值尽量大。显然取前$n$小作为$X$,剩下的作为$Y$最优。

    Code

     1 /**
     2  * Codeforces
     3  * Problem#1013C
     4  * Accepted
     5  * Time: 93ms
     6  * Memory: 800k 
     7  */ 
     8 #include <bits/stdc++.h>
     9 using namespace std;
    10 typedef bool boolean;
    11 
    12 const int N = 2e5 + 5;
    13 
    14 int n;
    15 int ar[N];
    16 
    17 inline void init() {
    18     scanf("%d", &n);
    19     n <<= 1;
    20     for (int i = 1; i <= n; i++)
    21         scanf("%d", ar + i);
    22 }
    23 
    24 inline void solve() {
    25     sort(ar + 1, ar + n + 1);
    26     n >>= 1;
    27     long long res = (ar[n] - ar[1]) * 1ll * (ar[n << 1] - ar[n + 1]);
    28     for (int i = 2; i <= n; i++)
    29         res = min((ar[i + n - 1] - ar[i]) * 1ll * (ar[n << 1] - ar[1]), res);
    30     cout << res << endl;
    31 }
    32 
    33 int main() {
    34     init();
    35     solve();
    36     return 0;
    37 }
    Problem C

    Problem D Chemical table

    题目大意

      有一个$n imes m$的网格图,如果三个有原料的格子恰好在恰好围住它们的最小矩形的三个"顶点"上,那么剩下的一个"顶点"能自动填上原料。现在有$q$个位置填上了原料。你可以在某个格子上放置原料,问如果要整张图都填满原料,至少还要放置多少原料。

      一个比较经典的模型?

      每行每列分别建一个点,$(i, j)$ 有原料那么第 $i$ 行向第 $j$ 列连一条边。

      然后算算连通块数就能算答案了。

    Code

     1 /**
     2  * Codeforces
     3  * Problem#1013D
     4  * Accepted
     5  * Time: 109ms
     6  * Memory: 6500k
     7  */
     8 #include <bits/stdc++.h>
     9 using namespace std;
    10 typedef bool boolean;
    11 
    12 const int N = 2e5 + 5;
    13 
    14 int n, m, q;
    15 boolean v1[N], v2[N];
    16 int uf[N << 1];
    17 
    18 int find(int x) {
    19     return (uf[x] == x) ? (x) : (uf[x] = find(uf[x])); 
    20 } 
    21 
    22 inline void init() {
    23     scanf("%d%d%d", &n, &m, &q);
    24     for (int i = 1; i <= n + m; i++)
    25         uf[i] = i;
    26     for (int i = 1, x, y; i <= q; i++) {
    27         scanf("%d%d", &x, &y);
    28         uf[find(x)] = find(y + n);
    29     }
    30 }
    31 
    32 int res = -1;
    33 inline void solve() {
    34     for (int i = 1; i <= n + m; i++)
    35         if (find(i) == i)
    36             res++;
    37     printf("%d
    ", res);
    38 }
    39 
    40 int main() {
    41     init();
    42     solve();
    43     return 0;
    44 }
    Problem D

    Problem E Hills

    题目大意

      有一条连绵起伏的山脉,第$i$个山峰的高度是$h_{i}$。有一个工程队,每小时能将任意一座山的高度减少1。一个山峰能建立房子当且仅当它两边的山峰高度严格小于它。要求输出当建立$1. cdots, left lceil frac{n}{2} ight ceil$个房子的时候至少需要工程队施工的时间。

      显然用$f[i][j][0 / 1]$表示考虑到第$i$座山峰,已经建立了$j$个房子,当期山峰是否建立房子的最少施工时间。

      首先如果一个地方要建立房子,那么会贪心地使周围两座山的高度尽量高(因为这样花的时间少),因此如果知道一座山两边有没有盖房子,这座山在最优的情况下的高度是确定的。

      转移也比较显然。如果当前山峰没有建立房子,那么从$i - 1$转移。

      如果当前山峰建立了房子,那么前一座山一定不能建房子。考虑$i - 2$座山上有没有建房子,如果建立了,那么补上第$i - 1$座山的高度差,以及减少第$i + 1$座山的高度的耗时。如果没有建房子,直接计算耗时转移。

    Code

     1 /**
     2  * Codeforces
     3  * Problem#1013E
     4  * Accepted
     5  * Time: 124ms
     6  * Memory: 98100k 
     7  */ 
     8 #include <bits/stdc++.h>
     9 #ifndef WIN32
    10 #define Auto "%lld"
    11 #else
    12 #define Auto "%I64d"
    13 #endif
    14 using namespace std;
    15 typedef bool boolean;
    16 
    17 #define ll long long
    18 
    19 const int N = 5e3 + 5;
    20 
    21 int n, hn;
    22 int ar[N];
    23 int f[N][N >> 1][2];
    24 
    25 inline void init() {
    26     scanf("%d", &n);
    27     hn = (n + 1) >> 1;
    28     for (int i = 1; i <= n; i++)
    29         scanf("%d", ar + i);
    30 }
    31 
    32 int calc(int p) {
    33     if (p < 1)    return 0;
    34     return ((ar[p - 1] < ar[p]) ? (0) : (ar[p - 1] - ar[p] + 1)) + ((ar[p + 1] < ar[p]) ? (0) : (ar[p + 1] - ar[p] + 1));
    35 }
    36 
    37 int calc2(int a) {
    38     if (a < 1)    return calc(a + 2);
    39     int res = ((ar[a - 1] < ar[a]) ? (0) : (ar[a - 1] - ar[a] + 1));
    40     res += (ar[a + 1] < min(ar[a], ar[a + 2])) ? (0) : (ar[a + 1] - min(ar[a], ar[a + 2]) + 1);
    41     res += (ar[a + 3] < ar[a + 2]) ? (0) :(ar[a + 3] - ar[a + 2] + 1);
    42     return res;
    43 }
    44 
    45 int res[N];
    46 
    47 inline void solve() {
    48     memset(f, 0x7f, sizeof(f));
    49     ar[0] = -1e5 + 1, ar[n + 1] = -1e5;
    50     for (int i = 0; i <= n; i++)
    51         f[i][0][0] = 0;
    52     f[1][1][1] = calc(1), f[1][0][0] = 0;
    53     for (int i = 2; i <= n; i++)
    54         for (int j = 0; j <= hn && j <= ((i + 1) >> 1); j++) {
    55             if (!j)
    56                 f[i][j][0] = f[i - 1][j][0];
    57             else {
    58                 f[i][j][0] = min(f[i - 1][j][0], f[i - 1][j][1]);
    59                 f[i][j][1] = min(f[i - 2][j - 1][0] + calc(i), f[i - 2][j - 1][1] - calc(i - 2) + calc2(i - 2));
    60 //                cerr << i << " " << calc(i) << " " << calc2(i - 2) << " " << calc(i - 2) << " " << f[i - 2][j][0] << endl;
    61             }
    62         }
    63 
    64     memset(res, 0x7f, sizeof(res));
    65     for (int i = 1; i <= n; i++)
    66         for (int j = 1; j <= hn; j++)
    67             res[j] = min(res[j], f[i][j][0]), res[j] = min(res[j], f[i][j][1]);
    68     for (int i = 1; i <= hn; i++)
    69         printf("%d ", res[i]);
    70 }
    71 
    72 int main() {
    73     init();
    74     solve();
    75     return 0;
    76 }
    Problem E

    Problem F AB-Strings

    题目大意

      有两个只含字符'a'、'b'的字符串。一次操作是指交换这两个字符串的可空前缀。问使得每个串内只包含一种字符最少的操作数。要求输出方案。保证至少有一个'a'和'b'。

      显然把已经连续的相同字符断开不优,因此把连续的相同缩在一起。

      然后有用的状态就只有两个串的串长,以及开头的字符是否相同。

      因此我们可以暴力动态规划。

      但是感觉这玩意决策不会太多,因为每次至多只会消掉两个字符。

      于是我们可以对小数据进行动态规划,并打表。

      然后发现第一列、第二列、第一行、第二行除去前几项决策4个一循环。

      剩下的决策与它们的长度差模4的余数有关。

      然后再写个链表模拟一下。交上去就过了。

      如果哪位佬会证明,麻烦在评论区内写一写。

    Code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef bool boolean;
     4 
     5 const int N = 60;
     6 boolean vis[N][N][2];
     7 int f[N][N][2], p1[N][N][2], p2[N][N][2];
     8 int s1[N], s2[N];
     9 
    10 void update(int &f, int& p1, int& p2, int val, int sl, int sr) {
    11     if (val < f || (val == f && (sl + sr < p1 + p2)) || (sl + sr == p1 + p2 && sl < p1))
    12         f = val, p1 = sl, p2 = sr;
    13 }
    14 
    15 int dp(int l, int r, int dif) {
    16     if (!l || !r)
    17         return 0x7f7f7f7f;
    18     if (l == 1 && r == 1)
    19         return (dif == 1) ? (0) : (0x7f7f7f7f);
    20     if (vis[l][r][dif])
    21         return f[l][r][dif];
    22     vis[l][r][dif] = true;
    23     for (int sl = 0; sl <= l; sl++)
    24         for (int sr = 0; sr <= r; sr++) {
    25             if (!sl && !sr)
    26                 continue;
    27             for (int i = 0; i < sr; i++)
    28                 s1[i] = (dif + i) & 1;
    29             s1[sr] = sl & 1;
    30             for (int i = 0; i < sl; i++)
    31                 s2[i] = i & 1;
    32             s2[sl] = (dif + sr) & 1;
    33             int red1 = 0, red2 = 0;
    34             for (int i = 1; i <= sr && i < l - sl + sr; i++)
    35                 red1 += (s1[i] == s1[i - 1]);
    36             for (int i = 1; i <= sl && i < r + sl - sr; i++)
    37                 red2 += (s2[i] == s2[i - 1]);
    38             if (!red1 && !red2)
    39                 continue;
    40 //            cerr << l << " " << r << " " << dif << " " << sl << " " << sr << " -> " << l + sr - sl - red1 << " " << r + sl - sr - red2 << " " << (s1[0] != s2[0]) << endl;
    41             update(f[l][r][dif], p1[l][r][dif], p2[l][r][dif], dp(l + sr - sl - red1, r + sl - sr - red2, s1[0] != s2[0]) + 1, sl, sr);
    42         }
    43     return f[l][r][dif];
    44 }
    45 
    46 int n, m, d;
    47 int main() {
    48 //    cin >> n >> m >> d;
    49     cin >> d;
    50     memset(vis, false, sizeof(vis));
    51     memset(f, 0x7f, sizeof(f));
    52 //    cout << dp(n, m, d) << endl; 
    53     freopen("list.txt", "w", stdout);
    54     for (int i = 1; i <= 25; i++, cout << endl)
    55         for (int j = 1; j <= 15; j++) {
    56             dp(i, j, d);
    57             cout << "(" << p1[i][j][d] << ", " << p2[i][j][d] << ") "; 
    58 //            assert(p1[i][j][d] == p1[min(i, 10)][min(j, 10)][d]);
    59 //            assert(p2[i][j][d] == p2[min(i, 10)][min(j, 10)][d]);
    60         }
    61     return 0;
    62 }
    Table Maker
      1 /**
      2  * Codeforces
      3  * Problem#1013F
      4  * Accepted
      5  * Time: 109ms
      6  * Memory: 8000k
      7  */
      8 #include <bits/stdc++.h>
      9 using namespace std;
     10 typedef bool boolean;
     11 
     12 const int N = 44;
     13 boolean vis[N][N][2];
     14 int f[N][N][2], p1[N][N][2], p2[N][N][2];
     15 int s1[N], s2[N];
     16 
     17 void update(int &f, int& p1, int& p2, int val, int sl, int sr) {
     18     if (val < f || (val == f && (sl + sr < p1 + p2)))
     19         f = val, p1 = sl, p2 = sr;
     20 }
     21 
     22 int dp(int l, int r, int dif) {
     23     if (!l || !r)
     24         return 0x7f7f7f7f;
     25     if (l == 1 && r == 1)
     26         return (dif == 1) ? (0) : (0x7f7f7f7f);
     27     if (vis[l][r][dif])
     28         return f[l][r][dif];
     29     vis[l][r][dif] = true;
     30     for (int sl = 0; sl <= l; sl++)
     31         for (int sr = 0; sr <= r; sr++) {
     32             if (!sl && !sr)
     33                 continue;
     34             for (int i = 0; i < sr; i++)
     35                 s1[i] = (dif + i) & 1;
     36             s1[sr] = sl & 1;
     37             for (int i = 0; i < sl; i++)
     38                 s2[i] = i & 1;
     39             s2[sl] = (dif + sr) & 1;
     40             int red1 = 0, red2 = 0;
     41             for (int i = 1; i <= sr && i < l - sl + sr; i++)
     42                 red1 += (s1[i] == s1[i - 1]);
     43             for (int i = 1; i <= sl && i < r + sl - sr; i++)
     44                 red2 += (s2[i] == s2[i - 1]);
     45             if (!red1 && !red2)
     46                 continue;
     47 //            cerr << l << " " << r << " " << dif << " " << sl << " " << sr << " -> " << l + sr - sl - red1 << " " << r + sl - sr - red2 << " " << (s1[0] != s2[0]) << endl;
     48             update(f[l][r][dif], p1[l][r][dif], p2[l][r][dif], dp(l + sr - sl - red1, r + sl - sr - red2, s1[0] != s2[0]) + 1, sl, sr);
     49         }
     50     return f[l][r][dif];
     51 }
     52 
     53 typedef class Node {
     54     public:
     55         Node* suf;
     56         int col, s;
     57         
     58         Node() {    }
     59         Node(Node* suf, int col, int s):suf(suf), col(col), s(s) {    }
     60 }Node;
     61 
     62 int d;
     63 int l = 1, r = 1;
     64 Node *stl, *str;
     65 Node nl[200005], nr[200005]; 
     66 char buf[200005];
     67 
     68 inline void init() {
     69     int c1, c2;
     70     scanf("%s", buf);
     71     c1 = buf[0];
     72     nl[0] = Node(nl + 1, -1, -233333);
     73     nl[1] = Node(nl + 2, c1, 1);
     74     for (int i = 1; buf[i]; i++)
     75         if (buf[i] == buf[i - 1])
     76             nl[l].s++;
     77         else
     78             l += 1, nl[l] = Node(nl + l + 1, buf[i], 1);
     79     nl[l + 1].s = -1; 
     80     scanf("%s", buf);
     81     c2 = buf[0];
     82     nr[0] = Node(nr + 1, -1, -233333);
     83     nr[1] = Node(nr + 2, c2, 1);
     84     for (int i = 1; buf[i]; i++)
     85         if (buf[i] == buf[i - 1])
     86             nr[r].s++;
     87         else
     88             r += 1, nr[r] = Node(nr + r + 1, buf[i], 1); 
     89     nr[r + 1].s = -1;
     90     d = (c1 != c2);
     91     stl = nl, str = nr;
     92 }
     93 
     94 pair<int, int> swapS(int sl, int sr, int& l, int& r) {
     95     Node *pl = stl, *psl, *pr = str, *psr;
     96     int rl = 0, rr = 0;
     97     for (int i = 0; i < sl; i++)
     98         pl = pl->suf, rl += pl->s;
     99     for (int i = 0; i < sr; i++)
    100         pr = pr->suf, rr += pr->s;
    101     psl = pl->suf, psr = pr->suf;
    102     swap(stl, str);
    103     pl->suf = psr;
    104     pr->suf = psl;
    105     if (pl->s > 0 && psr->s > 0 && pl->col == psr->col) {
    106         pl->s += psr->s;
    107         pl->suf = psr->suf;
    108         r--;
    109     }
    110     if (pr->s > 0 && psl->s > 0 && pr->col == psl->col) {
    111         pr->s += psl->s;
    112         pr->suf = psl->suf;
    113         l--;
    114     }
    115     return pair<int, int> (rl, rr);
    116 }
    117 
    118 pair<int, int> st1[4] = {pair<int, int>(1, 0), pair<int, int>(2, 1), pair<int, int>(3, 0), pair<int, int>(1, 0)};
    119 pair<int, int> st2[4] = {pair<int, int>(1, 0), pair<int, int>(2, 1), pair<int, int>(0, 1), pair<int, int>(1, 0)};
    120 pair<int, int> st3[4] = {pair<int, int>(0, 1), pair<int, int>(0, 3), pair<int, int>(0, 3), pair<int, int>(0, 1)};
    121 pair<int, int> st4[4] = {pair<int, int>(1, 1), pair<int, int>(2, 0), pair<int, int>(3, 1), pair<int, int>(1, 1)};
    122 pair<int, int> st5[4] = {pair<int, int>(1, 1), pair<int, int>(3, 1), pair<int, int>(3, 1), pair<int, int>(1, 1)};
    123 pair<int, int> st6[4] = {pair<int, int>(0, 2), pair<int, int>(1, 3), pair<int, int>(1, 3), pair<int, int>(1, 1)};
    124 
    125 pair<int, int> g(int x, int y, int d) {
    126     if (x <= 10 && y <= 10) {
    127         dp(x, y, d);
    128         return pair<int, int>(p1[x][y][d], p2[x][y][d]);
    129     }
    130     if (!d) {
    131         if (y == 1)
    132             return st1[x % 4];
    133         if (y == 2)
    134             return st2[x % 4];
    135         if (x == 1)
    136             return st3[y % 4];
    137         if (x == 2)
    138             return (y % 4 == 1) ? (pair<int, int>(1, 2)) : (pair<int, int>(0, 1));
    139         return ((((x - y) % 4 + 4) % 4) == 1) ? (pair<int, int>(1, 0)) : (pair<int, int>(0, 1));
    140     } else {
    141         if (y == 1)
    142             return st4[x % 4];
    143         if (y == 2)
    144             return st5[x % 4];    
    145         if (x == 1)
    146             return (y % 4 == 2) ? (pair<int, int>(1, 3)) : (pair<int, int>(0, 2));
    147         if (x == 2)
    148             return st6[y % 4];
    149         return ((((x - y) % 4 + 4) % 4) == 2) ? (pair<int, int>(0, 2)) : (pair<int, int>(1, 1));
    150     }
    151 }
    152 
    153 vector< pair<int, int> > opt;
    154 inline void solve() {
    155     memset(vis, false, sizeof(vis));
    156     memset(f, 0x7f, sizeof(f));
    157     while (l > 1 || r > 1) {
    158         pair<int, int> s = g(l, r, d);
    159         int sl = s.first, sr = s.second;
    160         l = l - sl + sr, r = r + sl - sr;
    161         opt.push_back(swapS(sl, sr, l, r));
    162         d = (stl->suf->col != str->suf->col);
    163     }
    164     printf("%d
    ", (signed) opt.size());
    165     for (int i = 0; i < (signed) opt.size(); i++)
    166         printf("%d %d
    ", opt[i].first, opt[i].second);
    167 }
    168 
    169 int main() {
    170     init();
    171     solve();
    172     return 0;
    173 }
    Problem F
  • 相关阅读:
    目标检测的图像特征提取之(一)HOG特征
    压缩跟踪Compressive Tracking
    计算机视觉领域的一些牛人博客,研究机构等的网站链接
    运动检测(前景检测)之(二)混合高斯模型GMM
    最简单的目标跟踪(模版匹配)
    Kalman滤波器从原理到实现
    前景目标检测(总结)
    ViBe(Visual Background extractor)背景建模或前景检测
    paramiko不能通过cd改变路径分析
    SecureCRT SSH主机秘钥配置文件管理
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9393198.html
Copyright © 2011-2022 走看看