zoukankan      html  css  js  c++  java
  • Wannafly挑战赛28 Solution

    A:msc和mas

    Solved.

    考虑斐波那契数列,即最多加45次即会超过1e9,直接暴力即可

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3  
     4 int a, b, l;
     5  
     6 int solve(int st)
     7 {
     8     int A = a, B = b;
     9     while (1)
    10     {
    11         if (st == 1)
    12         {
    13             if (A > l) return printf("Yes");
    14             else
    15             {
    16                 int B0 = B;
    17                 while (B < 2 * B0) B += A;
    18             }
    19         }
    20         else
    21         {
    22             if (B > l) return printf("No");
    23             else
    24             {
    25                 int A0 = A;
    26                 while (A < 2 * A0) A += B;
    27             }
    28         }
    29         st ^= 1;
    30     }
    31 }
    32  
    33 int main()
    34 {
    35     while (scanf("%d%d%d", &a, &b, &l) != EOF)
    36     {
    37         solve(1); putchar(' ');
    38         solve(0); putchar('
    ');
    39     }
    40     return 0;
    41 }
    View Code

    B:msc和mcc

    Solved.

    考虑如果有一个区间满足,那么左右两边扩展区间肯定也是满足的

    再考虑从左到右,如果$1-x满足,那么2-y满足的话, 显然有y >= x$

    那么只需要双指针找到以i为左界,找到最近的右界,那么这个点的贡献就是n - r + 1

    再考虑怎么判断是否合法

    不难发现,只有mscmcc 和 mccmsc 两种情况,注意其中可以加入其他字符,但是最终取出的子序列都会归结到这两种情况 都判断一下即可

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 100010
     6 int n; 
     7 char str[N];
     8 set <int> m, s, c;
     9 int st_m[2], pos_s, pos_c[2];
    10 
    11 bool check1()
    12 {
    13     // mscmcc
    14     if (s.upper_bound(st_m[0]) == s.end()) return false;
    15     pos_s = *s.upper_bound(st_m[0]); 
    16     if (c.upper_bound(pos_s) == c.end()) return false;
    17     pos_c[0] = *c.upper_bound(pos_s);
    18     if (c.upper_bound(max(st_m[1], pos_c[0])) == c.end()) return false;
    19     pos_c[1] = *c.upper_bound(max(st_m[1], pos_c[0]));
    20     if (c.upper_bound(pos_c[1]) == c.end()) return false;
    21     return true; 
    22 }
    23 
    24 bool check2()
    25 {
    26     // mccmsc
    27     if (c.upper_bound(st_m[0]) == c.end()) return false;
    28     pos_c[0] = *c.upper_bound(st_m[0]);
    29     if (c.upper_bound(pos_c[0]) == c.end()) return false;
    30     pos_c[1] = *c.upper_bound(pos_c[0]);
    31     if (s.upper_bound(st_m[1]) == s.end()) return false;
    32     pos_s = *s.upper_bound(st_m[1]);
    33     if (c.upper_bound(max(pos_s, pos_c[1])) == c.end()) return false; 
    34     return true;
    35 }
    36     
    37 bool ok()
    38 {
    39     if (m.size() < 2) return false;
    40     if (s.size() < 1) return false;
    41     if (c.size() < 3) return false;
    42     st_m[0] = *m.begin(); m.erase(m.begin()); 
    43     st_m[1] = *m.begin(); m.insert(st_m[0]); 
    44     if (check1()) return true;
    45     if (check2()) return true;
    46     return false; 
    47 }
    48 
    49 int main()
    50 {
    51     while (scanf("%d", &n) != EOF)
    52     {
    53         m.clear(); s.clear(); c.clear();
    54         ll res = 0; 
    55         scanf("%s", str + 1);
    56         for (int i = 1, r = 0; i <= n; ++i)
    57         {
    58             while (r < n && !ok())
    59             {
    60                 ++r;  
    61                 if (str[r] == 'm') m.insert(r);
    62                 else if (str[r] == 's') s.insert(r);
    63                 else c.insert(r); 
    64             }
    65             if (!ok()) break;
    66             res += n - r + 1; 
    67             if (str[i] == 'm') m.erase(i);
    68             else if (str[i] == 's') s.erase(i);
    69             else c.erase(i); 
    70         }
    71         printf("%lld
    ", res); 
    72     }
    73     return 0;
    74 }
    View Code

    C:msc的宠物

    Upsolved.

    先二分答案,再DP求解最少需要删去的边数。

    设$g[u] 表示 以 u 为根的子树下最少需要删去的边数,f[u][x] 表示以u为根的子树下u所处的连通块中点权最大值为x的情况下最少需要删去的边数$

    $对于u 和 v  如果 a[u] < x 并且 a[v] < x 并且 abs(a[u] - a[v])  < x  那么 u 和 v 就可以同属一个连通块 $

    $那么转移就是 f[u][x] += min(g[v] +1, f[v][x])$

    其他情况的转移都是 $f[u][x] += g[v] +1$

    最后 $g[u] = min(f[u][x])$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 1010
     5 #define INF 0x3f3f3f3f
     6 #define ll long long
     7 int n, k, a[N], f[N][N], g[N]; ll x;
     8 vector <int> G[N];
     9 
    10 void dp(int u, int fa = 0)
    11 {
    12     for (auto v : G[u]) if (v != fa)
    13     {
    14         dp(v, u);
    15         for (int i = 1; i <= n; ++i)
    16         { 
    17             if (a[u] <= a[i] && a[v] <= a[i] && abs(a[u] - a[v]) <= x) 
    18                 f[u][i] += min(g[v] + 1, f[v][i]); 
    19             else
    20                 f[u][i] += g[v] + 1;
    21         }
    22     }
    23     for (int i = 1; i <= n; ++i)
    24         g[u] = min(g[u], f[u][i]);
    25 }
    26 
    27 bool check()
    28 {
    29     memset(g, 0x3f, sizeof g);
    30     for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j)
    31         f[i][j] = (abs(a[i] - a[j]) <= x) ? 0 : INF;
    32     dp(1);  
    33     return g[1] <= k;
    34 }
    35 
    36 void Run()
    37 {
    38     while (scanf("%d%d", &n, &k) != EOF)
    39     {
    40         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    41         for (int i = 1, u, v; i < n; ++i)
    42         {
    43             scanf("%d%d", &u, &v);
    44             G[u].push_back(v);
    45             G[v].push_back(u);
    46         } 
    47         ll l = 0, r = 2000000000, res = -1;
    48         while (r - l >= 0)
    49         {
    50             x = (l + r) >> 1; 
    51             if (check())
    52             {
    53                 res = x;
    54                 r = x - 1;
    55             }
    56             else
    57                 l = x + 1;
    58         }
    59         printf("%d
    ", res);
    60     }
    61 }
    62 
    63 int main()
    64 {
    65     #ifdef LOCAL
    66         freopen("Test.in", "r", stdin);
    67     #endif 
    68 
    69     Run();
    70     return 0;
    71 }
    View Code

    D:msc的背包

    Unsolved.

    E:msc的序列

    Unsolved.

    F:msc的无向图

    Unsolved.

  • 相关阅读:
    UVALive 7146 (贪心+少许数据结构基础)2014acm/icpc区域赛上海站
    hdu 1754 I Hate It(树状数组区间求最值)2007省赛集训队练习赛(6)_linle专场
    【进阶——树状数组】 区间求最值
    软件测试作业4
    软件测试作业三 尝试使用JUnit
    软件测试作业2:读代码回答问题
    软件测试作业1:描述一个曾遇到的错误
    hdu1064Financial Management
    hdu1161Eddy's mistakes
    hdu1020Encoding
  • 原文地址:https://www.cnblogs.com/Dup4/p/9937585.html
Copyright © 2011-2022 走看看