• Codeforces Round #321 div2


    好像前几场的题解忘记写了, Orz 状态太差, 平均出两题   都不好意思写了 , 连掉4场, 都要哭晕了。

    很水的一场, 写完A B C就去睡了  D题其实不难, E题研究Ing(已用一种奇怪的姿势AC了

    Problem_A:

    题意:

      给一个长度为n的序列, 找出最长不下降子序列。

    思路:

      线性扫一遍, 每读入一个数就判断下是否和前面的组成不下降子序列, 维护最大答案和当前序列长度即可(注意处理最后一个序列即可)。

    代码:

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <ctime>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <string>
    12 #include <vector>
    13 #include <fstream>
    14 #include <iterator>
    15 #include <iostream>
    16 #include <algorithm>
    17 using namespace std;
    18 #define LL long long
    19 #define INF 0x3f3f3f3f
    20 #define MOD 1000000007
    21 #define eps 1e-6
    22 #define MAXN 100010
    23 #define MAXM 100
    24 #define dd {cout<<"debug"<<endl;}
    25 #define pa {system("pause");}
    26 #define p(x) {printf("%d
    ", x);}
    27 #define pd(x) {printf("%.7lf
    ", x);}
    28 #define k(x) {printf("Case %d: ", ++x);}
    29 #define s(x) {scanf("%d", &x);}
    30 #define sd(x) {scanf("%lf", &x);}
    31 #define mes(x, d) {memset(x, d, sizeof(x));}
    32 #define do(i, x) for(i = 0; i < x; i ++)
    33 #define dod(i, x, l) for(i = x; i >= l; i --)
    34 #define doe(i, x) for(i = 1; i <= x; i ++)
    35 int n;
    36 int f[MAXN];
    37 
    38 int main()
    39 {
    40     int ans_i = 0;
    41     int max_num = 0;
    42     scanf("%d", &n);
    43     for(int i = 0; i < n; i ++)
    44     {
    45         scanf("%d", &f[i]);
    46         if(i == 0) continue;
    47         if(f[i] < f[i - 1]) 
    48         {
    49             max_num = max(max_num, (i - 1 - ans_i + 1));
    50             ans_i = i;
    51         }
    52     }
    53     if(ans_i != n - 1)
    54     {
    55         max_num = max(max_num, (n - 1 - ans_i + 1));
    56     }
    57     if(n == 1) max_num = 1;
    58     printf("%d
    ", max_num);
    59     return 0;
    60 }
    View Code

    Problem_B:

    题意:

      你想邀请朋友来参加聚会, 每个朋友都有一个财富值和亲密度, 当你邀请的朋友中存在两个人财富值之差大于等于d, 那么就有有个朋友感到自己比较穷,但是你并不像让这种情况发生。

      求使得邀请过来的朋友满足上诉要求,并求最大的亲密度和。

    思路:

      首先邀请朋友的第一要素是财富值, 所以先按财富值排序, 细想一下, 这个题和A题很像。这里就是找到所有满足要求的区间,然后比较得到最大财富值。

      线性扫一遍, 维护区间起点即可。

    代码:

      

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <ctime>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <string>
    12 #include <vector>
    13 #include <fstream>
    14 #include <iterator>
    15 #include <iostream>
    16 #include <algorithm>
    17 using namespace std;
    18 #define LL long long
    19 #define INF 0x3f3f3f3f
    20 #define MOD 1000000007
    21 #define eps 1e-6
    22 #define MAXN 100010
    23 #define MAXM 100
    24 #define dd {cout<<"debug"<<endl;}
    25 #define pa {system("pause");}
    26 #define p(x) {printf("%d
    ", x);}
    27 #define pd(x) {printf("%.7lf
    ", x);}
    28 #define k(x) {printf("Case %d: ", ++x);}
    29 #define s(x) {scanf("%d", &x);}
    30 #define sd(x) {scanf("%lf", &x);}
    31 #define mes(x, d) {memset(x, d, sizeof(x));}
    32 #define do(i, x) for(i = 0; i < x; i ++)
    33 #define dod(i, x, l) for(i = x; i >= l; i --)
    34 #define doe(i, x) for(i = 1; i <= x; i ++)
    35 struct node
    36 {
    37     int m;
    38     int s;
    39 };
    40 int n, d;
    41 struct node f[MAXN];
    42 bool cmp(struct node x, struct node y)
    43 {
    44     return x.m < y.m;
    45 }
    46 
    47 int main()
    48 {
    49     LL pre_id = 1;
    50     LL ans = 0;
    51     LL temp = 0;
    52     scanf("%d %d", &n, &d);
    53     for(int i = 1; i <= n; i ++)
    54         scanf("%d %d", &f[i].m, &f[i].s);
    55     sort(f + 1, f + n + 1, cmp);        
    56     for(int i = 1; i <= n; i ++)
    57     {
    58         if(f[i].m - f[pre_id].m < d)
    59         {
    60             temp += f[i].s;
    61         }
    62         else 
    63         {
    64             ans = max(ans, temp);
    65             while(f[i].m - f[pre_id].m >= d) 
    66             {
    67                 temp -= f[pre_id].s;
    68                 pre_id ++;
    69             }
    70             temp += f[i].s;
    71         }
    72     }
    73     ans = max(ans, temp);
    74     printf("%I64d
    ", ans);
    75     return 0;
    76 }
    View Code

     Problem_C:

    题意:

      给一棵树, 根节点是你的家, 叶子节点是饭馆,每个节点可能存在猫, 你想去饭馆吃饭, 但是又怕猫。如果存在一条路径, 路径上连续的猫的个数 > m个,那么你就可以不能去那个饭馆, 因为你怕猫。

      求你能到达的饭馆个数。

    思路:

      搜索, dfs, 搜索出所有路径, 然后判断路径是否满足要求,搜索下一个状态时需要当前状态, 因为要判断是否是连续的。建边双向建, 叶子节点即所有边都被访问过。

    代码:

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <ctime>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <string>
    12 #include <vector>
    13 #include <fstream>
    14 #include <iterator>
    15 #include <iostream>
    16 #include <algorithm>
    17 using namespace std;
    18 #define LL long long
    19 #define INF 0x3f3f3f3f
    20 #define MOD 1000000007
    21 #define eps 1e-6
    22 #define MAXN 100010
    23 #define MAXM 100
    24 #define dd {cout<<"debug"<<endl;}
    25 #define pa {system("pause");}
    26 #define p(x) {printf("%d
    ", x);}
    27 #define pd(x) {printf("%.7lf
    ", x);}
    28 #define k(x) {printf("Case %d: ", ++x);}
    29 #define s(x) {scanf("%d", &x);}
    30 #define sd(x) {scanf("%lf", &x);}
    31 #define mes(x, d) {memset(x, d, sizeof(x));}
    32 #define do(i, x) for(i = 0; i < x; i ++)
    33 #define dod(i, x, l) for(i = x; i >= l; i --)
    34 #define doe(i, x) for(i = 1; i <= x; i ++)
    35 int n, m;
    36 int ans = 0;
    37 vector <int> edge[MAXN];
    38 int num[MAXN];
    39 bool vis[MAXN];
    40 void init()
    41 {
    42     memset(vis, false, sizeof(vis));
    43     for(int i = 0; i < MAXN; i ++)
    44         edge[i].clear();
    45     int ans = 0;
    46 }
    47 bool is_ok(int u)
    48 {
    49     for(int i = 0; i < edge[u].size(); i ++)
    50         if(!vis[edge[u][i]]) return false;
    51     return true;
    52 }
    53 void dfs(int root, int cat_num)
    54 {
    55     vis[root] = true;
    56     if(cat_num > m) return ;
    57     if(is_ok(root))
    58     {
    59         ans ++;
    60         return ;
    61     }
    62     for(int i = 0; i < edge[root].size(); i ++)
    63     {
    64         int v = edge[root][i];
    65         if(!vis[v])
    66         {
    67             if(num[v])
    68                 dfs(v, cat_num + num[v]);
    69             else 
    70                 dfs(v, 0);
    71         }
    72     }
    73 }
    74 
    75 int main()
    76 {
    77     init();
    78     scanf("%d %d", &n, &m);
    79     for(int i = 1; i <= n; i ++)
    80         scanf("%d", &num[i]);
    81     int x, y;
    82     for(int i = 0; i < n - 1; i ++)
    83     {
    84         scanf("%d %d", &x, &y);
    85         edge[x].push_back(y);
    86         edge[y].push_back(x);
    87     }
    88     dfs(1, num[1]);
    89     printf("%d
    ", ans);
    90     return 0;
    91 }
    View Code

    Problem_D:

    题意:

      去饭馆吃饭(又吃饭, 囧),菜单上有n道菜, 你想吃m道菜, 且每道最多吃一次, 每一道菜有一个欢乐度, 如果你吃了x 后 又吃y 那么你将得到 c的欢乐度。

      求问你能获得的最大欢乐度。

    思路:

      最多只有18道菜, 答案又是求最优解, 第一反应就是状压。

      因为x y 要按顺序, 连续吃下去才能得到c的欢乐度, 所以需要记录一下最后吃的是什么。

      那么状态设为:dp[staues][last], staues为二进制集合, last为当前状态最后吃的那道菜,

      so,转移方程就出来了, 因为每道菜要么吃, 要么不吃, 就成了个状压的01背包问题了。

      dp[staues | (1 <<  i)][i] = max(dp[staues |(1 <<  i)][i], dp[staues][last] + a[i] + ruler[last][i]), 初始化时注意下初始为-1, 因为有可能出现0的情况(全部的a[i] = 0)

    代码:

      

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <ctime>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <string>
    12 #include <vector>
    13 #include <fstream>
    14 #include <iterator>
    15 #include <iostream>
    16 #include <algorithm>
    17 using namespace std;
    18 #define LL long long
    19 #define INF 0x3f3f3f3f
    20 #define MOD 1000000007
    21 #define eps 1e-6
    22 #define MAXN 19
    23 #define MAXM (1 << 19)
    24 #define dd {cout<<"debug"<<endl;}
    25 #define pa {system("pause");}
    26 #define p(x) {printf("%d
    ", x);}
    27 #define pd(x) {printf("%.7lf
    ", x);}
    28 #define k(x) {printf("Case %d: ", ++x);}
    29 #define s(x) {scanf("%d", &x);}
    30 #define sd(x) {scanf("%lf", &x);}
    31 #define mes(x, d) {memset(x, d, sizeof(x));}
    32 #define do(i, x) for(i = 0; i < x; i ++)
    33 #define dod(i, x, l) for(i = x; i >= l; i --)
    34 #define doe(i, x) for(i = 1; i <= x; i ++)
    35 LL dp[MAXM][MAXN];
    36 LL ruler[MAXN][MAXN];
    37 LL a[MAXN];
    38 int n, m, k;
    39 void read()
    40 {
    41     int x, y;
    42     LL c;
    43     memset(ruler, 0, sizeof(ruler));
    44     scanf("%d %d %d", &n, &m, &k);
    45     for(int i = 0; i < n; i ++)
    46         scanf("%lld", &a[i]);
    47     for(int i = 0; i < k; i ++)
    48     {
    49         scanf("%d %d %lld", &x, &y, &c);
    50         -- x;
    51         -- y;
    52         ruler[x][y] = c;
    53     }
    54 }
    55 bool is_ok(int x)
    56 {
    57     int num = 0;
    58     while(x)
    59     {
    60         if(x & 1) num ++;
    61         x /= 2;
    62     }
    63     return num == m;
    64 }
    65 LL solve()
    66 {
    67     memset(dp, -1, sizeof(dp));
    68     LL ans = 0;
    69     for(int staues = 0; staues < (1 << n); staues ++)
    70     {
    71         for(int last = 0; last < n; last ++)
    72         {
    73             int u = 1 << last;
    74             if(staues == 0)
    75             {
    76                 dp[staues | u][last] = a[last];
    77             }
    78             else if(dp[staues][last] != -1)
    79             {
    80                 for(int cas = 0; cas < n; cas ++)
    81                 {
    82                     int v = 1 << cas;
    83                     if(staues & v) continue;
    84                     dp[staues | v][cas] = max(dp[staues | v][cas], dp[staues][last] + a[cas] + ruler[last][cas]);
    85                 }
    86             }
    87             if(is_ok(staues)) ans = max(ans, dp[staues][last]);
    88         }
    89     }
    90     return ans;
    91 }
    92 
    93 int main()
    94 {
    95     read();
    96     printf("%lld
    ", solve());
    97     return 0;
    98 }
    View Code

    Problem_E:

    题意;

      给一个长度为n的字符串, 这个字符串由0~9组成, 现在有2种操作:

      1:l, r, c, 将[l, r]这段区间上的数字全变成c。

      2:l, r, d, 判断以l , r开头, 长度为d的两个字符串是否相等。

      对每个第二种操作, 输出结果。

    思路:

      这道题正解应该是线段树 + hash的, 将数字进行hash, 然后第一个操作就是线段树中的区间修改, 第二个操作就是查询是否想等。

      然而, 这道题还有一个神奇的解法:仅用两个系统函数 + 一个if 就解出来了。

        memset(), memcmp()

      用memset将l, r 进行覆盖, 用memcmp进行判断。

      这里给出第二种解法, Orz 其实第一种我还不会。

    代码:

      

     1 #include <stdio.h>
     2 #include <string.h>
     3 #define MAXN 100010
     4 int n, m, k;
     5 char s[MAXN];
     6 
     7 int main()
     8 {
     9     int op, l, r, val;
    10 
    11     memset(s, '', sizeof(s));
    12 
    13     scanf("%d %d %d", &n, &m, &k);
    14     scanf("%s", s);
    15 
    16     for (int i = 0; i < m + k; ++ i)
    17     {
    18         scanf("%d %d %d %d", &op, &l, &r, &val);
    19         -- l;
    20         -- r;
    21         if(op == 1)
    22             memset(s + l, val + '0', r - l + 1);
    23         else 
    24             printf(!memcmp(s + l, s + l + val, r - l + 1 - val)? "YES
    " : "NO
    ");
    25     }
    26     return 0;
    27 }
    View Code
  • 相关阅读:
    计算机图形学——几何变换的数学基础
    算法设计与分析——多边形游戏(动态规划)
    算法设计与分析——凸多边形最优三角剖分(动态规划)
    计算机图形学——反走样
    Android 5.0 API
    Android 6.0 API
    Android 7.0 新增功能和api
    Android 8.0 功能和 API
    Android P 功能和 API
    解决华为手机无法输出Debug级别log的问题
  • 原文地址:https://www.cnblogs.com/By-ruoyu/p/4833633.html
Copyright © 2020-2023  润新知