• CCPC-Wannafly Winter Camp Day4 (Div2, onsite)


    Replay


    Dup4:

    • 两轮怎么退火啊?
    • 简单树形dp都不会了,送了那么多罚时
    • 简单题都不想清楚就乱写了,喵喵喵?

     X:

    • 欧拉怎么回路啊, 不会啊。
    • 还是有没有手误?未思考清楚或者未检查就提交, 导致自己白送罚时。

    A:夺宝奇兵

    Solved.

    考虑$所有i >= 2 需要跟i - 1 连两条边 只有两种可能 取最小的一种$

    $注意n的两个点要连一条边$

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 const int maxn = 1e5 + 10;
     8 
     9 struct node{
    10     int x1, x2, y1, y2;
    11 }arr[maxn];
    12 
    13 ll calc(int i,int j)
    14 {
    15     ll ans1 = abs(arr[i].x1 - arr[j].x1) + abs(arr[i].y1 - arr[j].y1) + abs(arr[i].x2 - arr[j].x2) + abs(arr[i].y2 - arr[j].y2);
    16     ll ans2 = abs(arr[i].x1 - arr[j].x2) + abs(arr[i].y1 - arr[j].y2) + abs(arr[i].x2 - arr[j].x1) + abs(arr[i].y2 - arr[j].y1);
    17     return min(ans1, ans2);
    18 }
    19 
    20 int n , m;
    21 
    22 int main()
    23 {
    24     while(~scanf("%d %d", &n, &m))
    25     {
    26         for(int i = 1; i <= n; ++i) scanf("%d %d %d %d", &arr[i].x1, &arr[i].y1, &arr[i].x2, &arr[i].y2);
    27         ll ans = 0;
    28         for(int i = 2; i <= n; ++i) ans += calc(i, i - 1);
    29         ans += abs(arr[n].x1 - arr[n].x2) + abs(arr[n].y1 - arr[n].y2);
    30         printf("%lld
    ", ans);
    31     }
    32     return 0;
    33 }
    View Code

    C:最小边覆盖

    Solved.

    考虑$No的情况$

    • 存在一个点的度数为0(没有被覆盖)
    • 存在一条边所连接的两个点其度数 >= 2 即这条边去掉还是个最小边覆盖
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 300010
     5 #define pii pair <int, int>
     6 int n, m;
     7 pii G[N];
     8 int d[N];
     9 
    10 bool f()
    11 {
    12     for (int i = 1; i <= n; ++i) if (!d[i]) return false;
    13     for (int i = 1; i <= m; ++i)
    14     {
    15         int u = G[i].first, v = G[i].second;
    16         if (d[u] >= 2 && d[v] >= 2)
    17             return false;
    18     }
    19     return true;
    20 }
    21 
    22 int main()
    23 {
    24     while (scanf("%d%d", &n, &m) != EOF)
    25     {
    26         memset(d, 0, sizeof d);
    27         for (int i = 1, u, v; i <= m; ++i)
    28         {
    29             scanf("%d%d", &u, &v);
    30             ++d[u], ++d[v];
    31             G[i] = pii(u, v);
    32         }
    33         puts(f() ? "Yes" : "No");
    34     }
    35     return 0;
    36 }
    View Code

    F:小小马

    Solved.

    因为不同颜色出现次数相同, 所以步数一定是奇数。

    暴力跑出大数据的状态, 发现颜色相同就输出No, 否则输出Yes。

    小数据暴力跑即可

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int maxn = 1e6 + 10;
     6 
     7 struct node{
     8     int x, y;
     9     int step;
    10     node(){}
    11     node(int x, int y, int step): x(x), y(y), step(step){}
    12 };
    13 
    14 int n, m;
    15 int sx, sy, ex, ey;
    16 int vis[11][maxn][2];
    17 int dir[8][2] = {-2, -1, -2, 1, -1, -2, -1, 2, 1, -2, 1, 2, 2, -1, 2, 1};
    18 
    19 int judge(int x, int y,int step)
    20 {
    21     if(x < 1 || x > n || y < 1 || y > m || vis[x][y][step % 2]) return false;
    22     else return true;    
    23 }
    24 
    25 void BFS()
    26 {
    27     memset(vis, 0, sizeof vis);
    28     queue<node>q;
    29     q.push(node(sx, sy, 0));
    30     while(!q.empty())
    31     {
    32         node st = q.front();
    33         q.pop();
    34         node now = st;
    35         now.step++;
    36         for(int i = 0; i < 8; ++i)
    37         {
    38             now.x = st.x + dir[i][0];
    39             now.y = st.y + dir[i][1];
    40             if(judge(now.x, now.y, now.step))
    41             {
    42                 vis[now.x][now.y][now.step % 2] = 1;
    43                 q.push(now);
    44             }
    45         }
    46     }
    47 }
    48 
    49 int main()
    50 {
    51     while(~scanf("%d %d", &n, &m))
    52     {
    53         scanf("%d %d", &sx, &sy);
    54         scanf("%d %d", &ex, &ey);
    55         if(n < 10 || m < 10)
    56         {
    57             if(n > m) 
    58             {
    59                 swap(n, m);
    60                 swap(sx, sy);
    61                 swap(ex, ey);
    62             }
    63             BFS();
    64             if(vis[ex][ey][1]) puts("Yes");
    65             else puts("No");
    66         }
    67         else
    68         {
    69             int ans1 = (sx + sy) % 2;
    70             int ans2 = (ex + ey) % 2;
    71             if(ans1 != ans2) puts("Yes");
    72             else puts("No");
    73         }        
    74     }
    75     return 0;
    76 }
    View Code

    G:置置置换

    Solved.

    $在已知1-n的方案数, 枚举n+1出现的位置$

    $当枚举到位置x的时候, 选出x-1个数放在前x个, 然后计算方案数 统计即可$

    $2 cdot ans_{n + 1} = sumlimits_{i = 0}^{n} C_n^i cdot ans_i cdot ans_{n - i}$

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 const ll MOD = (ll)1e9 + 7;
     8 const int maxn = 1e3 + 10;
     9 
    10 int n;
    11 ll fac[maxn];
    12 ll inv[maxn];
    13 ll invfac[maxn];
    14 
    15 ll ans[maxn];
    16 
    17 void Init()
    18 {
    19     fac[1] = 1, inv[1] = 1, invfac[1] = 1;
    20     for(int i = 2; i < maxn; ++i)
    21     {
    22         fac[i] = fac[i - 1] * i % MOD;
    23         inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
    24         invfac[i] = invfac[i - 1] * inv[i]  % MOD;
    25     }
    26 }
    27 
    28 ll calc(int n, int m)
    29 {
    30     if(n == m || m == 0) return 1ll;
    31     return fac[n] * invfac[m] % MOD * invfac[n - m] % MOD;
    32 }
    33 
    34 
    35 int main()
    36 {
    37     Init();
    38     ans[0] = ans[1] = 1;
    39     for(int i = 1; i + 1 < maxn; ++i)
    40     {
    41         for(int j = 0; j <= i; ++j)
    42         {
    43             ans[i + 1] = (ans[i + 1] + calc(i, j) * ans[j] % MOD * ans[i - j] % MOD) % MOD;
    44         }
    45         ans[i + 1] = (ans[i + 1] * inv[2]) % MOD;
    46     }
    47     while (scanf("%d", &n) != EOF)
    48     {
    49         printf("%lld
    ", ans[n]);
    50     }
    51     return 0;
    52 }
    View Code



    I:咆咆咆哮

    Solved.

    考虑如果选择$a_i的个数固定为x,那么对于所有选取b_i的卡牌来说它的贡献是固定的$

    枚举$x, 再贪心选取即可$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 1010
     6 int n, a[N], b[N];
     7 
     8 ll f(int x)
     9 {
    10     priority_queue <ll> pq;
    11     ll res = 0;
    12     for (int i = 1; i <= n; ++i) 
    13     {
    14         res += a[i];
    15         pq.push(1ll * b[i] * x - a[i]);
    16     }    
    17     for (int i = 1; i <= n - x; ++i) 
    18     {
    19         res += pq.top();
    20         pq.pop();
    21     }
    22     return res;
    23 }
    24 
    25 int main()
    26 {
    27     while (scanf("%d", &n) != EOF)
    28     {
    29         for (int i = 1; i <= n; ++i) scanf("%d%d", a + i, b + i);
    30         ll res = 0;
    31         for (int i = 1; i <= n; ++i)
    32             res = max(res, f(i));
    33         printf("%lld
    ", res);
    34     }
    35     return 0;
    36 }
    View Code

    Div1:

    三分

    好像满足凸性? 我不会证啊。..

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 100010
     6 int n, a[N], b[N];
     7 
     8 ll check(int x)
     9 {
    10     ll res = 0;
    11     priority_queue <ll> pq;
    12     for (int i = 1; i <= n; ++i)
    13     {
    14         res = res + a[i];
    15         pq.push(1ll * b[i] * x - a[i]);
    16     }
    17     for (int i = n - x; !pq.empty() && i; --i)
    18     {
    19         res += pq.top(); pq.pop();
    20     }
    21     return res;
    22 }
    23 
    24 int main()
    25 {
    26     while (scanf("%d", &n) != EOF)
    27     {
    28         for (int i = 1; i <= n; ++i) scanf("%d%d", a + i, b + i);
    29         int l = 0, r = n; ll res = 0;
    30         while (r - l >= 0)
    31         {
    32             int midl = (l + r) >> 1;
    33             int midr = (midl + r) >> 1;
    34             ll tmpl = check(midl); 
    35             ll tmpr = check(midr);
    36             if (tmpl <= tmpr)
    37             {
    38                 res = max(res, tmpr);
    39                 l = midl + 1;
    40             }
    41             else
    42             {
    43                 res = max(res, tmpl);
    44                 r = midr - 1;
    45             }
    46         }
    47         printf("%lld
    ", res);
    48     }
    49     return 0;
    50 }
    View Code

    K:两条路径

    Solved.

    考虑$x作为交它的权值要被算上$

    在考虑两条路径可以选取端点,端点的选择在其儿子对应的子树中选取一个点且仅能选取一个

    树形DP即可

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 100010
     6 #define INFLL 0x3f3f3f3f3f3f3f3f
     7 int n, q;
     8 ll val[N];
     9 vector <int> G[N];
    10 ll Bit[35], f[N];
    11 
    12 void DFS(int u, int fa)
    13 {
    14     f[u] = -INFLL;
    15     for (auto v : G[u]) if (v != fa)
    16     {
    17         DFS(v, u);
    18         f[u] = max(f[u], f[v]);
    19     }    
    20     f[u] = max(f[u], 0ll);
    21     f[u] += val[u];
    22 }
    23 
    24 void out(ll x)
    25 {
    26     if (x < 0) putchar('-'), x = -x;
    27     string res = "";
    28     while (x)
    29     {
    30         res += (x % 2 + '0');  
    31         x /= 2;
    32     }
    33     reverse(res.begin(), res.end());
    34     cout << res << "
    ";
    35 }
    36 
    37 int main()
    38 {
    39     Bit[0] = 1;
    40     for (int i = 1; i <= 30; ++i) Bit[i] = Bit[i - 1] << 1;
    41     while (scanf("%d", &n) != EOF)
    42     {
    43         for (int i = 1; i <= n; ++i) G[i].clear();
    44         for (int i = 1, x; i <= n; ++i) 
    45         {
    46             scanf("%d", &x);
    47             if (!x) 
    48             {
    49                 val[i] = 0;
    50                 continue;
    51             }
    52             int vis = 1;
    53             if (x < 0)
    54             {
    55                 x = -x;
    56                 vis = -1;
    57             }
    58             --x;
    59             val[i] = Bit[x] * vis;
    60         }
    61         for (int i = 1, u, v; i < n; ++i) 
    62         {
    63             scanf("%d%d", &u, &v);
    64             G[u].push_back(v);
    65             G[v].push_back(u); 
    66         }
    67         int x;
    68         scanf("%d", &q);
    69         while (q--)
    70         {
    71             scanf("%d", &x);
    72             priority_queue <ll> pq;
    73             for (auto v : G[x]) 
    74             {
    75                 DFS(v, x);
    76                 pq.push(f[v]);
    77             }
    78             ll res = val[x];
    79             for (int i = 1; i <= 4 && !pq.empty() && pq.top() > 0; ++i)
    80             {
    81                 res += pq.top(); pq.pop(); 
    82             }
    83             //cout << res << endl;
    84             out(res);
    85         }
    86     }
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    从URL输入到页面展现,过程中发生了什么?
    Android ADB被占用 重启 ADB方法
    Android消息处理:EventBus、BroadCast和Handler-优缺点比较
    Android EventBus 的使用
    浅谈Java/Android下的注解
    如何理解Android中的xmlns
    【LeetCode】165
    【leetcode】155
    【LeetCode】12 & 13
    【LeetCode】66 & 67- Plus One & Add Binary
  • 原文地址:https://www.cnblogs.com/Dup4/p/10311074.html
Copyright © 2020-2023  润新知