zoukankan      html  css  js  c++  java
  • CF集萃1

    因为cf上一堆水题,每个单独开一篇博客感觉不太好,就直接放一起好了。

    CF1096D Easy Problem

    给定字符串,每个位置删除要代价。求最小代价使之不含子序列"hard"。

    设f[i][f]表示前i个删到只匹配f位子序列的最小代价。转移看代码吧。O(n)

     1 #include <bits/stdc++.h>
     2 
     3 typedef long long LL;
     4 const int N = 100010;
     5 
     6 int a[N];
     7 LL f[N][5];
     8 char str[N];
     9 
    10 int main() {
    11     int n;
    12     scanf("%d", &n);
    13     scanf("%s", str + 1);
    14     for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    15 
    16     int tag = 0;
    17     for(int i = 1; i <= n; i++) {
    18         if(tag == 0 && str[i] == 'h') tag++;
    19         if(tag == 1 && str[i] == 'a') tag++;
    20         if(tag == 2 && str[i] == 'r') tag++;
    21         if(tag == 3 && str[i] == 'd') tag++;
    22     }
    23     if(tag != 4) {
    24         printf("0
    ");
    25         return 0;
    26     }
    27 
    28     for(int i = 1; i <= n; i++) {
    29         f[i][0] = f[i - 1][0] + a[i] * (str[i] == 'h');
    30         f[i][1] = f[i - 1][1] + a[i] * (str[i] == 'a');
    31         f[i][2] = f[i - 1][2] + a[i] * (str[i] == 'r');
    32         f[i][3] = f[i - 1][3] + a[i] * (str[i] == 'd');
    33         if(str[i] == 'h') f[i][1] = std::min(f[i][1], f[i - 1][0]);
    34         if(str[i] == 'a') f[i][2] = std::min(f[i][2], f[i - 1][1]);
    35         if(str[i] == 'r') f[i][3] = std::min(f[i][3], f[i - 1][2]);
    36     }
    37 
    38     LL ans = std::min(std::min(f[n][0], f[n][1]), std::min(f[n][2], f[n][3]));
    39 
    40     printf("%lld
    ", ans);
    41     return 0;
    42 }
    AC代码

    CF1036C Classy Numbers

    问[l, r]之间有多少个数满足非0数码不超过三个。

    裸数位DP......注意每次读完要把char数组清空...

      1 /**
      2  * There is no end though there is a start in space. ---Infinity.
      3  * It has own power, it ruins, and it goes though there is a start also in the star. ---Finite.
      4  * Only the person who was wisdom can read the most foolish one from the history.
      5  * The fish that lives in the sea doesn't know the world in the land.
      6  * It also ruins and goes if they have wisdom.
      7  * It is funnier that man exceeds the speed of light than fish start living in the land.
      8  * It can be said that this is an final ultimatum from the god to the people who can fight.
      9  *
     10  * Steins;Gate
     11  */
     12 
     13 #include <bits/stdc++.h>
     14 
     15 typedef long long LL;
     16 const int N = 25;
     17 
     18 LL f[N][5][2];
     19 char str[N], str1[N], str2[N];
     20 
     21 LL DFS(int k, int cnt, int z) {
     22     if(cnt > 3) return 0;
     23     if(!k) {
     24         return 1;
     25     }
     26     if(f[k][cnt][z] != -1) {
     27         return f[k][cnt][z];
     28     }
     29     LL ans = 0;
     30     if(cnt < 3) {
     31         for(int i = 1; i <= 9; i++) {
     32             ans += DFS(k - 1, cnt + 1, 1);
     33         }
     34     }
     35     ans += DFS(k - 1, cnt, z);
     36     return f[k][cnt][z] = ans;
     37 }
     38 
     39 LL DFS_2(int k, int cnt, int z) {
     40     if(cnt > 3) return 0;
     41     if(!k) return 1;
     42     int lm = str[k] - '0';
     43     //printf("k = %d cnt = %d z = %d lm = %d 
    ", k, cnt, z, lm);
     44     LL ans = DFS_2(k - 1, cnt + (lm != 0), z | (lm != 0));
     45     if(lm) {
     46         ans += DFS(k - 1, cnt, z);
     47     }
     48     for(int i = 1; i < lm; i++) {
     49         ans += DFS(k - 1, cnt + 1, 1);
     50     }
     51     return ans;
     52 }
     53 /*
     54 1
     55 29000000000091 29000000000099
     56 
     57 */
     58 inline void dec(int &n) {
     59     for(int i = 1; i <= n; i++) {
     60         if(str[i] != '0') {
     61             str[i]--;
     62             break;
     63         }
     64         else str[i] = '9';
     65     }
     66     if(str[n] == '0') n--;
     67     return;
     68 }
     69 
     70 int main() {
     71     memset(f, -1, sizeof(f));
     72     LL l, r;
     73     int T;
     74     scanf("%d", &T);
     75     for(int i = 1; i <= T; i++) {
     76         scanf("%s%s", str1 + 1, str2 + 1);
     77         int n = strlen(str2 + 1);
     78         memcpy(str + 1, str2 + 1, sizeof(char) * n);
     79         std::reverse(str + 1, str + n + 1);
     80 
     81         /*for(int j = 1; j <= n; j++) {
     82             putchar(str[j]);
     83         }
     84         puts("");*/
     85 
     86         LL ans = DFS_2(n, 0, 0);
     87         //printf("temp ans = %lld 
    ", ans);
     88         memset(str2 + 1, 0, n * sizeof(char));
     89         n = strlen(str1 + 1);
     90         memcpy(str + 1, str1 + 1, n * sizeof(char));
     91         std::reverse(str + 1, str + n + 1);
     92         dec(n);
     93 
     94         /*for(int j = 1; j <= n; j++) {
     95             putchar(str[j]);
     96         }
     97         puts("");*/
     98 
     99         ans -= DFS_2(n, 0, 0);
    100         printf("%lld
    ", ans);
    101         memset(str1 + 1, 0, n * sizeof(char));
    102     }
    103 
    104     return 0;
    105 }
    AC代码

    CF1132C Painting the Fence

    给定n个区间,选出n - 2个区间使它们覆盖的总长度最大。转为删去两个区间。

    去重 + 排序。考虑到答案要么相邻要么不相邻,相邻的预处理前后缀覆盖总长之后直接枚举。

    预处理出只删每个区间的时候的覆盖减少量为di。当不相邻的时候,考虑到减少总量就是他们两个的di之和。

    于是枚举一个区间,拿一个数据结构维护[1, i - 2]之间的最小d值即可。

    注意答案不能比总长度还优。复杂度O(nlogn) / O(n)

      1 /**
      2  * There is no end though there is a start in space. ---Infinity.
      3  * It has own power, it ruins, and it goes though there is a start also in the star. ---Finite.
      4  * Only the person who was wisdom can read the most foolish one from the history.
      5  * The fish that lives in the sea doesn't know the world in the land.
      6  * It also ruins and goes if they have wisdom.
      7  * It is funnier that man exceeds the speed of light than fish start living in the land.
      8  * It can be said that this is an final ultimatum from the god to the people who can fight.
      9  *
     10  * Steins;Gate
     11  */
     12 
     13 #include <bits/stdc++.h>
     14 
     15 const int N = 5010;
     16 
     17 struct Node {
     18     int l, r;
     19     inline bool operator < (const Node &w) const {
     20         if(l != w.l) return l < w.l;
     21         return r > w.r;
     22     }
     23 }node[N], stk[N]; int top;
     24 
     25 int n, m, sl[N], sr[N], del[N], pw[N], ST[N][20];
     26 
     27 namespace t1 {
     28     int d[N];
     29     inline void solve() {
     30         for(int i = 1; i <= n; i++) {
     31             d[node[i].l]++;
     32             d[node[i].r + 1]--;
     33         }
     34         int ans = 0, now = 0;
     35         for(int i = 1; i <= m; i++) {
     36             now += d[i];
     37             ans += (now > 0);
     38         }
     39         printf("%d
    ", ans);
     40         return;
     41     }
     42 }
     43 
     44 namespace t2 {
     45     inline void solve() {
     46         int ans = 0;
     47         for(int i = 1; i <= n; i++) {
     48             ans = std::max(ans, std::min(sl[i - 1] + sr[i + 1], sr[1]));
     49         }
     50         printf("%d
    ", ans);
     51         return;
     52     }
     53 }
     54 
     55 inline void prework() {
     56     for(int i = 1; i <= n; i++) { /// get sl del
     57         sl[i] = sl[i - 1] + node[i].r - std::max(node[i].l, node[i - 1].r + 1) + 1;
     58         del[i] = std::min(node[i].r, node[i + 1].l - 1) - std::max(node[i].l, node[i - 1].r + 1) + 1;
     59         del[i] = std::max(del[i], 0);
     60     }
     61     for(int i = n; i >= 1; i--) { /// get sr
     62         sr[i] = sr[i + 1] + std::min(node[i].r, node[i + 1].l - 1) - node[i].l + 1;
     63     }
     64     return;
     65 }
     66 
     67 inline void prework2() {
     68     for(int i = 2; i <= n; i++) {
     69         pw[i] = pw[i >> 1] + 1;
     70     }
     71     for(int i = 1; i <= n; i++) ST[i][0] = del[i];
     72     for(int j = 1; j <= pw[n]; j++) {
     73         for(int i = 1; i + (1 << j) - 1 <= n; i++) {
     74             ST[i][j] = std::min(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
     75         }
     76     }
     77     return;
     78 }
     79 
     80 inline int getMin(int l, int r) {
     81     if(l > r) return 0x3f3f3f3f;
     82     int t = pw[r - l + 1];
     83     return std::min(ST[l][t], ST[r - (1 << t) + 1][t]);
     84 }
     85 
     86 int main() {
     87     scanf("%d%d", &m, &n);
     88     for(int i = 1; i <= n; i++) {
     89         scanf("%d%d", &node[i].l, &node[i].r);
     90     }
     91 
     92     std::sort(node + 1, node + n + 1);
     93     int k = 2;
     94     for(int i = 1; i <= n; i++) {
     95         if(top && stk[top].r >= node[i].r) {
     96             k--;
     97             continue;
     98         }
     99         stk[++top] = node[i];
    100     }
    101     n = top;
    102     memcpy(node + 1, stk + 1, n * sizeof(Node));
    103 
    104     if(k <= 0) {
    105         t1::solve();
    106         return 0;
    107     }
    108     node[n + 1].l = node[n + 1].r = 0x3f3f3f3f;
    109     prework();
    110 
    111     if(k == 1) {
    112         t2::solve();
    113         return 0;
    114     }
    115 
    116     /// solve
    117 
    118     int ans = 0;
    119     for(int i = 1; i < n; i++) { /// choose i  i + 1
    120         ans = std::max(ans, std::min(sl[i - 1] + sr[i + 2], sr[1]));
    121     }
    122     /// not neighbor
    123 
    124     prework2();
    125 
    126     for(int i = 1; i <= n; i++) {
    127         ans = std::max(ans, sr[1] - del[i] - getMin(1, i - 2));
    128     }
    129     printf("%d
    ", ans);
    130     return 0;
    131 }
    AC代码

    CF1132F Clear the String

    给定字符串,一次可以删去连续的一段相同字符,问最少多少次删光。

    有一个很直观的想法是f[l][r][k]表示把[l, r]删成k个str[l]的最小代价,发现不好O(1)转移...

    然后又考虑f[l][r][k]表示[l, r]右端加上k个str[r]之后删去的最小代价,也不会转移...

    尝试n2状态,发现这个k,完全没必要记具体个数,因为无论多少个都是一次删掉。

    于是采用CF1025D的套路,fa[l][r]表示把[l, r]删成只剩str[l - 1]的最小代价,fb是str[r + 1],ans是删光的最小代价。

    转移fa的时候考虑str[r]和str[l - 1]是否相同并以此转移。转移ans的时候选出一个位置,左边的fb + 右边的fa转移。

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 510;
     4 
     5 int fa[N][N], fb[N][N], ans[N][N];
     6 char str[N];
     7 
     8 inline void exmin(int &a, const int &b) {
     9     if(a > b) a = b;
    10     return;
    11 }
    12 
    13 int main() {
    14     memset(fa, 0x3f, sizeof(fa));
    15     memset(fb, 0x3f, sizeof(fb));
    16     memset(ans, 0x3f, sizeof(ans));
    17     int n;
    18     scanf("%d", &n);
    19     scanf("%s", str + 1);
    20     for(int i = 1; i <= n; i++) {
    21         fa[i][i] = (str[i] != str[i - 1]);
    22         fb[i][i] = (str[i] != str[i + 1]);
    23         ans[i][i] = 1;
    24     }
    25     for(int len = 2; len <= n; len++) {
    26         for(int l = 1; l + len - 1 <= n; l++) {
    27             int r = l + len - 1;
    28             /// fa[l][r]  fb[l][r]  ans[l][r]
    29             if(str[r] == str[l - 1]) {
    30                 exmin(fa[l][r], fa[l][r - 1]);
    31             }
    32             else {
    33                 for(int k = l; k < r; k++) {
    34                     exmin(fa[l][r], fa[l][k] + ans[k + 1][r]);
    35                 }
    36             }
    37             if(str[l] == str[r + 1]) {
    38                 exmin(fb[l][r], fb[l + 1][r]);
    39             }
    40             else {
    41                 for(int k = l; k < r; k++) {
    42                     exmin(fb[l][r], ans[l][k] + fb[k + 1][r]);
    43                 }
    44             }
    45             for(int k = l + 1; k < r; k++) {
    46                 exmin(ans[l][r], fb[l][k - 1] + fa[k + 1][r] + 1);
    47             }
    48             exmin(ans[l][r], fa[l + 1][r] + 1);
    49             exmin(ans[l][r], fb[l][r - 1] + 1);
    50             exmin(fa[l][r], ans[l][r]);
    51             exmin(fb[l][r], ans[l][r]);
    52             //printf("[%d %d] l = %d r = %d ans = %d 
    ", l, r, fa[l][r], fb[l][r], ans[l][r]);
    53         }
    54     }
    55     printf("%d
    ", ans[1][n]);
    56     return 0;
    57 }
    AC代码

    然而本题还有多种简单一点的方法......

    就设f[l][r]表示把[l, r]删光的代价,考虑str[l]是如何被删的。显然要么是单独被删,要么是跟某些位置一起删。不妨设一起删的位置中第二个是k。

    枚举这个k,于是答案就是f[l + 1][k - 1] + f[k][r]

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 510;
     4 
     5 int f[N][N];
     6 char str[N];
     7 
     8 inline void exmin(int &a, const int &b) {
     9     if(a > b) a = b;
    10     return;
    11 }
    12 
    13 int main() {
    14     memset(f, 0x3f, sizeof(f));
    15     int n;
    16     scanf("%d", &n);
    17     scanf("%s", str + 1);
    18     for(int i = 1; i <= n; i++) {
    19         f[i][i] = 1;
    20     }
    21     for(int len = 2; len <= n; len++) {
    22         for(int l = 1; l + len - 1 <= n; l++) {
    23             int r = l + len - 1;
    24             /// fa[l][r]  fb[l][r]  ans[l][r]
    25             exmin(f[l][r], f[l + 1][r] + 1);
    26             if(str[l] == str[l + 1]) {
    27                 exmin(f[l][r], f[l + 1][r]);
    28             }
    29             for(int k = l + 2; k <= r; k++) {
    30                 if(str[k] == str[l]) {
    31                     exmin(f[l][r], f[l + 1][k - 1] + f[k][r]);
    32                 }
    33             }
    34         }
    35     }
    36     printf("%d
    ", f[1][n]);
    37     return 0;
    38 }
    AC代码

    CF1132D Stressful Training

    题意:有n个笔记本,一开始有ai格电,每分钟消耗bi格电。你要买一个每分钟充x格点的插头,使得这些笔记本都能撑过k分钟。问x的最小值。

    解:不难想到二分。然后check里每天挑最早没电的充电。如果直接用堆的话是nlog2n的,然而我卡过去了...

    实际上我们可以考虑把这些笔记本按照没电天来分类,发现同类笔记本我们不需要知道它们的相对大小,于是直接vector。然后从前往后扫一遍,就能做到线性。

    注意二分上界是1e12...

      1 #include <bits/stdc++.h>
      2 
      3 typedef long long LL;
      4 const int N = 200010;
      5 
      6 inline char gc() {
      7     static char buf[N], *p1(buf), *p2(buf);
      8     if(p1 == p2) p2 = (p1 = buf) + fread(buf, 1, N, stdin);
      9     return p1 == p2 ? EOF : *p1++;
     10 }
     11 
     12 template <class T> inline void read(T &x) {
     13     x = 0;
     14     register char c(gc());
     15     bool f(false);
     16     while(c < '0' || c > '9') {
     17         if(c == '-') f = true;
     18         c = gc();
     19     }
     20     while(c >= '0' && c <= '9') {
     21         x = x * 10 + c - 48;
     22         c = gc();
     23     }
     24     if(f) x = (~x) + 1;
     25     return;
     26 }
     27 
     28 struct Node {
     29     LL now, del;
     30     double x;
     31     Node(LL A = 0, LL B = 0) {
     32         now = A;
     33         del = B;
     34         x = (double)A / B;
     35     }
     36     inline bool operator < (const Node &w) const {
     37         return x > w.x;
     38     }
     39 }node[N];
     40 
     41 int n, k;
     42 LL a[N], b[N];
     43 std::priority_queue<Node> Q;
     44 
     45 inline bool check(LL x) {
     46     while(Q.size()) Q.pop();
     47     for(register int i = 1; i <= n; i++) {
     48         Q.push(node[i]);
     49     }
     50     for(register int i = 0; i < k; i++) {
     51         Node temp = Q.top();
     52         Q.pop();
     53         if(temp.now - temp.del * i < 0) {
     54             return false;
     55         }
     56         temp = Node(temp.now + x, temp.del);
     57         Q.push(temp);
     58     }
     59     Node temp = Q.top();
     60     if(temp.now - temp.del * k < 0) {
     61         return false;
     62     }
     63     return true;
     64 }
     65 
     66 int main() {
     67 
     68     read(n); read(k);
     69     k--;
     70     for(register int i = 1; i <= n; i++) {
     71         read(a[i]);
     72     }
     73     for(register int i = 1; i <= n; i++) {
     74         read(b[i]);
     75     }
     76     for(register int i = 1; i <= n; i++) {
     77         if(b[i] * k <= a[i]) {
     78             std::swap(a[i], a[n]);
     79             std::swap(b[i], b[n]);
     80             n--;
     81             i--;
     82         }
     83     }
     84 
     85     if(!n) {
     86         puts("0");
     87         return 0;
     88     }
     89 
     90     for(int i = 1; i <= n; i++) {
     91         node[i] = Node(a[i], b[i]);
     92     }
     93     std::sort(node + 1, node + n + 1);
     94 
     95     LL l = 1, r = 2e12;
     96     while(l < r) {
     97         LL mid = (l + r) >> 1;
     98         if(check(mid)) {
     99             r = mid;
    100         }
    101         else l = mid + 1;
    102     }
    103     if(r == 2e12) puts("-1");
    104     else {
    105         printf("%lld
    ", r);
    106     }
    107     return 0;
    108 }
    AC代码
  • 相关阅读:
    使用Result代替ResultSet作为方法返回值
    java项目使用的DBhelper类
    几种更新(Update语句)查询的方法【转】
    SQL sum case when then else【转】
    解决lucene 重复索引的问题
    在jsp中运用ajax实现同一界面不跳转处理事件
    IIS7如何实现访问HTTP跳转到HTTPS访问 转的
    完整备份数据库+差异备份,恢复到另外一台服务器
    windows mobile ,wince 系统,用代码启动cab文件安装
    compact framework windows mobile wm c#代码 创建快捷方式
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10618055.html
Copyright © 2011-2022 走看看