zoukankan      html  css  js  c++  java
  • ZOJ Monthly, June 2018 Solution

    A - Peer Review

    Water.

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int t, n;
     5 
     6 int main()
     7 {
     8     scanf("%d", &t);
     9     while (t--)
    10     {
    11         scanf("%d", &n);
    12         for (int i = 1; i <= n; ++i) printf("0%c", " 
    "[i == n]);
    13     }
    14     return 0;
    15 }
    View Code

    B - Boring Game

    Unsolved. 

    C - Enigma Machine

    Unsolved.

    D - Number Theory

    Unsolved.

    E - Chasing

    Solved.

    题意:两个人在一个二维平面上,刚开始两个人在第二象限或者第三象限,A跑到Y轴B就不能追了,B的速度是A的K倍,求B能否追到B

    思路:k < 0 那么必然不行

    k == 0 判断是不是在同一高度,如果是判断起始位置

    k > 0  假设y轴上存在某个点 使得A B 能够在该点相遇,列方程求解

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 double xa, xb, ya, yb, k;
     6 
     7 int main()
     8 {
     9     int t;
    10     scanf("%d", &t);
    11     while(t--)
    12     {
    13         scanf("%lf %lf %lf %lf %lf", &xa, &ya, &xb, &yb, &k);
    14         if(k < 1.0)
    15         {
    16             puts("N");
    17         }
    18         else if(k == 1.0)
    19         {
    20             if(ya != yb) puts("N");
    21             else if(xb < xa) puts("N");
    22             else puts("Y");
    23         }
    24         else
    25         {
    26             double a = k * k - 1.0;
    27             double b = -2.0 * k * k * ya + 2.0 * yb;
    28             double c = k * k * xa * xa - xb * xb + k * k * ya * ya - yb * yb;
    29             double d = b * b - 4.0 * a * c;
    30             if(d >= 0) puts("N");
    31             else puts("Y");
    32         }
    33     }    
    34     return 0;
    35 }
    View Code

    F - Carrot Gathering

    Unsolved.

    G - Virtual Singers

    Upsolved.

    题意:

    H - How Many Palindromes

    Unsolved.

     题意:

    有$n个A数和m个B数 m <= n,对每个B数都匹配一个A数,使得sum_{i = 1}^{i = m} |B[i] - A[i]| 最小$

    思路:

    考虑费用流的思想,维护三个堆

    将$A、B 数放在一起排序,然后从左往右枚举$

    $如果当前数是A$

      如果左边有未匹配的$B_1数,那么与之匹配即可,此操作不用考虑反悔操作$

      $因为假如有另一个B_2,使得B_2 与 这个A匹配更优$

      那么后面必然要有另一个$A_2 来匹配这个B_1 $

      $贡献是 A_2 - B_1 + B_2 - A_1 这个式子显然小于 A_2 - B_2 + A_1 - B_1$

      因为这四个数字存在大小关系

      $A_2 - B_1 大于 A_2 - B_2 + A_1 - B_1$

      如果左边没有未匹配的$B_1数,那么考虑B的反悔操作是否更优$

      $更优的话就反悔并且将代价取反并算上A往右匹配的贡献放入堆Q_A中, 相当于反悔操作$

    $如果当前数是B$

      $如果左边有未匹配的A数,那么与之匹配,并且将代价取反并且算上B往右匹配的贡献放入堆Q_C中$

      否则放入堆$Q_B$中表示还未匹配

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 100010
     6 int t, n, m; ll x;
     7 struct node 
     8 {
     9     ll v; int Type;
    10     node () {}
    11     node (ll v, int Type) : v(v), Type(Type) {}
    12     bool operator < (const node &r) const { return v < r.v; }   
    13 }arr[N << 1];
    14 priority_queue <ll, vector <ll> , greater <ll> > A, B, C;  
    15 
    16 int main()
    17 {
    18     scanf("%d", &t);
    19     while (t--)
    20     {
    21         while (!A.empty()) A.pop();
    22         while (!B.empty()) B.pop();
    23         while (!C.empty()) C.pop();
    24         scanf("%d%d", &n, &m);
    25         for (int i = 1; i <= n; ++i) 
    26         {
    27             scanf("%lld", &x);
    28             arr[i] = node(x, 0);
    29         }
    30         for (int i = 1; i <= m; ++i)
    31         {
    32             scanf("%lld", &x);
    33             arr[n + i] = node(x, 1);
    34         }
    35         sort(arr + 1, arr + 1 + n + m);
    36         ll res = 0;
    37         for (int i = 1; i <= n + m; ++i)
    38         {
    39             if (arr[i].Type == 1)
    40             {
    41                 if (!A.empty())
    42                 {
    43                     x = A.top(); A.pop();
    44                     res += arr[i].v + x;
    45                     C.push(-x - 2 * arr[i].v);
    46                 }
    47                 else 
    48                     B.push(-arr[i].v); 
    49             }
    50             else
    51             {
    52                 if (!B.empty())
    53                 {
    54                     x = B.top(); B.pop();
    55                     res += arr[i].v + x;
    56                 }
    57                 else if (!C.empty()) 
    58                 {
    59                     x = C.top(); 
    60                     if (arr[i].v + x < 0)
    61                     {
    62                         C.pop();
    63                         res += arr[i].v + x;
    64                         A.push(-x - 2 * arr[i].v);
    65                     }
    66                     else 
    67                         A.push(-arr[i].v);
    68                 }
    69                 else
    70                     A.push(-arr[i].v); 
    71             }
    72         }
    73         printf("%lld
    ", res);
    74     }
    75     return 0;
    76 }
    View Code

    I - District Division

    Solved.

    题意:给出一棵树,求能不能分成$frac{n}{k}$ 个连通块,使得每块个数为k

    思路:如果存在合法分法,那么必然存在某个子树大小为k,DFS下去,再回溯上来判断即可,遇到大小为k的子树就分块

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int maxn = 1e5 + 10;
     6 
     7 int n, k;
     8 
     9 int val[maxn];
    10 int fa[maxn];
    11 int vis[maxn];
    12 int cnt;
    13 vector<int>root;
    14 vector<int>G[maxn];
    15 
    16 void Init()
    17 {
    18     cnt = 0;
    19     root.clear();
    20     for(int i = 1; i <= n; ++i)
    21     {
    22         val[i] = vis[i] = 0;
    23         fa[i] = i;
    24         G[i].clear();
    25     }    
    26 }
    27 
    28 void DFS(int u, int pre)
    29 {
    30     val[u] = 1;
    31     fa[u] = pre;
    32     for(int i = 0, len = G[u].size(); i < len; ++i)
    33     {
    34         int v = G[u][i];
    35         if(v == pre) continue;
    36         DFS(v, u);
    37         val[u] += val[v];
    38     }
    39     if(val[u] == k)
    40     {
    41         cnt++;
    42         val[u] = 0;
    43         root.push_back(u);
    44     }
    45 }
    46 
    47 void DFS2(int u, int pre)
    48 {
    49     if(vis[u]) return ;
    50     vis[u] = 1;
    51     printf("%d%c", u, " 
    "[cnt == k]);
    52     cnt++;
    53     for(int i = 0, len = G[u].size(); i < len; ++i)
    54     {
    55         int v = G[u][i];
    56         if(v == pre) continue;
    57         DFS2(v, u);
    58     }
    59 }
    60 
    61 int main()
    62 {
    63     int t;
    64     scanf("%d", &t);
    65     while(t--)
    66     {
    67         scanf("%d %d", &n, &k);
    68         Init();
    69         for(int i = 1; i < n; ++i)
    70         {
    71             int u, v;
    72             scanf("%d %d", &u, &v);
    73             G[u].push_back(v);
    74             G[v].push_back(u);
    75         }
    76         DFS(1, -1);
    77         if(cnt != n / k)
    78         {
    79             puts("NO");
    80             continue;
    81         }
    82         puts("YES");
    83         for(int i = 0, len = root.size(); i < len; ++i)
    84         {
    85             cnt = 1;
    86             DFS2(root[i], fa[root[i]]);
    87         }
    88     }    
    89     return 0;
    90 }
    View Code

    J - Good Permutation

    Solved.

    题意:每次能够交换相邻两个数,求最少交换次数使得满足题目给出的序列条件

    思路:通过枚举每次在第一位的数,从而递推下一种状态,比如12345推出51234即加上5移到第一位的步数再减去5带来的贡献

     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 int n;
    10 int arr[maxn];
    11 int pos[maxn];
    12 int a[maxn];
    13 
    14 int lowbit(int p)
    15 {
    16     return p & (-p);
    17 }
    18 
    19 void update(int p)
    20 {
    21     while(p <= n)
    22     {
    23         a[p]++;
    24         p += lowbit(p);
    25     }
    26 }
    27 
    28 int query(int p)
    29 {
    30     int res = 0;
    31     while(p)
    32     {
    33         res += a[p];
    34         p -= lowbit(p);
    35     }
    36     return res;
    37 }
    38 
    39 int main()
    40 {
    41     int t;
    42     scanf("%d", &t);
    43     while(t--)
    44     {
    45         scanf("%d", &n);
    46         ll ans = 0;
    47         for(int i = 1; i <= n; ++i) a[i] = 0;
    48         for(int i = 1; i <= n; ++i)
    49         {
    50             scanf("%d", arr + i);
    51             pos[arr[i]] = i;
    52         }
    53         for(int i = n; i >= 1; --i)
    54         {
    55             ans += query(arr[i] - 1);
    56             update(arr[i]);
    57         }
    58         ll tmp = ans;
    59         for(int i = 1; i <= n; ++i)
    60         {
    61             tmp = tmp + n - pos[i] - (pos[i] - 1);
    62             ans = min(ans, tmp);
    63         }
    64         printf("%lld
    ", ans);
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    dotnet core 获取 MacAddress 地址方法
    dotnet core 获取 MacAddress 地址方法
    dotnet core 发布只带必要的依赖文件
    dotnet core 发布只带必要的依赖文件
    Developing Universal Windows Apps 开发UWA应用 问答
    Developing Universal Windows Apps 开发UWA应用 问答
    cmd 如何跨驱动器移动文件夹
    cmd 如何跨驱动器移动文件夹
    C++ 驱动开发 error LNK2019
    C++ 驱动开发 error LNK2019
  • 原文地址:https://www.cnblogs.com/Dup4/p/9884160.html
Copyright © 2011-2022 走看看