zoukankan      html  css  js  c++  java
  • Mail.Ru Cup 2018 Round 1

    A. Elevator or Stairs?

    签.

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 int x, y, z, t[3];
     5 
     6 int main()
     7 {
     8     while (scanf("%d%d%d", &x, &y, &z) != EOF)
     9     {
    10         for (int i = 0; i < 3; ++i) scanf("%d", t + i);
    11         int a = (abs(z - x) + abs(x - y)) * t[1] + 3 * t[2];
    12         int b = abs(x - y) * t[0];
    13         puts(a <= b ? "YES" : "NO");
    14     }
    15     return 0;
    16 }
    View Code

    B. Appending Mex

    签.

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 100010
     5 int n, a[N], vis[N], last;
     6 
     7 void solve()
     8 {
     9     for (int i = 1; i <= n; ++i)
    10     {
    11         while (vis[last + 1]) ++last;
    12         if (a[i] > last + 1) 
    13         {
    14             printf("%d
    ", i);
    15             return;
    16         }
    17         vis[a[i]] = 1;
    18     }
    19     puts("-1");
    20 }
    21 
    22 int main()
    23 {
    24     while (scanf("%d", &n) != EOF)
    25     {
    26         memset(vis, 0, sizeof vis); last = -1;
    27         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    28         solve();
    29     }
    30     return 0;
    31 }
    View Code

    C. Candies Distribution

    Upsolved.

    题意:

    一个序列,$a_i取值为[1, n]$

    告诉你$每个数左边有多少数大于你,记为l_i$

    $右边有多少数大于你,记为r_i$

    让你还原出这个序列,如果没有合法的输出$NO$

    思路:

    $我们知道一个数的l_i + r_i 越大,那么这个数越小$

    $那我们不妨令 a_i = n - l_i - r_i$

    $再检查一遍即可$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 1010
     5 int n, l[N], r[N], v[N];
     6 
     7 int main()
     8 {
     9     while (scanf("%d", &n) != EOF)
    10     {
    11         for (int i = 1; i <= n; ++i) scanf("%d", l + i);
    12         for (int i = 1; i <= n; ++i) scanf("%d", r + i);
    13         for (int i = 1; i <= n; ++i) v[i] = n - l[i] - r[i];
    14         bool flag = true;
    15         for (int i = 1; i <= n; ++i) 
    16         {
    17             for (int j = 1; j < i; ++j)
    18                 if (v[j] > v[i])
    19                     --l[i];
    20             for (int j = i + 1; j <= n; ++j)
    21                 if (v[j] > v[i])
    22                     --r[i];
    23             if (l[i] != 0 || r[i] != 0)
    24             {
    25                 flag = false;
    26                 break;
    27             }
    28         }
    29         if (!flag) puts("NO");
    30         else
    31         {
    32             puts("YES");
    33             for (int i = 1; i <= n; ++i) 
    34                 printf("%d%c", v[i], " 
    "[i == n]);
    35         }
    36     }
    37     return 0;
    38 }
    View Code

    D. Changing Array

    Upsolved.

    题意:

    给一个序列,$可以将每个位置上的数取反$

    $求最多有多少子区间的异或和不为0$

    思路:

    求最多有多少子区间$异或和不为0,比较困难$

    $正难则反,我们考虑反面,我们求最少有多少个子区间异或和为0$

    $我们知道一段区间l, r的异或和是S_r oplus S_[l - 1]$

    $S表示前缀异或$

    $那么一个序列的前缀异或里面如果有x个a, 那么子区间异或为0的个数为frac{a cdot (a - 1)}{2}$

    $我们考虑 b = ~a, 而且a, b之间可以互相转化,并且只能互相转化,而不能转化为其他的数字$

    $令x = a的个数, y = b的个数$

    $我们令n = x + y $

    $那么a, b构成的子区间个数就是 frac{x cdot (x - 1)}{2} + frac{y cdot (y - 1)}{2}$

    $将n = x + y 代入$

    $就得到一个一元二次方程,取对称轴即可$

    $我们考虑转化都是oplus (1 << k) - 1$

    转化两次即相当于没有转化

    $所以每个前缀异或都能转化为自己想要的那个数$

    $为什么不考虑前面的数转化了会影响到后面的前缀异或?$

    $那后面那个如果受影响了,再转化回来不就好了?$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 200010
     6 int n, k;
     7 int a[N];
     8 map <int, int> mp;
     9 
    10 int main()
    11 {
    12     while (scanf("%d%d", &n, &k) != EOF)
    13     {
    14         mp.clear(); mp[0] = 1;
    15         int d = (1 << k) - 1;
    16         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    17         for (int i = 1; i <= n; ++i)
    18         {
    19             a[i] ^= a[i - 1];
    20             ++mp[a[i]];
    21             if (mp.find(a[i] ^ d) == mp.end()) mp[a[i] ^ d] = 0;
    22         }
    23         ll res = 0;
    24         for (auto it : mp) if (it.first > (it.first ^ d))
    25         {
    26             int a = it.second, n = a + mp[it.first ^ d];
    27             int b = n / 2;
    28             res += (1ll * n * n + 2ll * b * b - 2ll * b * n - n) / 2;
    29         }
    30         printf("%lld
    ", 1ll * n * (n + 1) / 2 - res);
    31     }
    32     return 0;
    33 }
    View Code
  • 相关阅读:
    ArrayList用法
    MessageBox
    将文本文件导入Sql数据库
    在桌面和菜单中添加快捷方式
    泡沫排序
    Making use of localized variables in javascript.
    Remove double empty lines in Visual Studio 2012
    Using Operations Manager Connectors
    Clear SharePoint Designer cache
    Programmatically set navigation settings in SharePoint 2013
  • 原文地址:https://www.cnblogs.com/Dup4/p/10354410.html
Copyright © 2011-2022 走看看