• Codeforces Round #576 (Div. 2)


    A - City Day

    题意:给n,x,y和数组a[n],求最小的下标d,使得有a[d-x,d-x+1,……d-1,d+1,d-1,d+1,……d+y-1,d+y]都比a[d]小,若d-x<=0则从1开始,若d+y>n,则从n为结尾。

    分析:对于a[i],要在左端找到比a[i]大的且最近的数,在右端找到比a[i]大且最近的数,用单调栈。然后从1开始看到n,看到哪个符合条件就作为答案输出。

     1 #include <bits/stdc++.h>
     2 
     3 #define maxn 100005
     4 #define mod 1000000007
     5 #define inf 0x3f3f3f3f
     6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     7 #define ll long long
     8 #define LL long long
     9 using namespace std;
    10 int a[maxn];
    11 int l[maxn];
    12 int r[maxn];
    13 
    14 int main() {
    15     start;
    16     int n, x, y;
    17     cin >> n >> x >> y;
    18     int t = 0;
    19     for (int i = 1; i <= n; ++i)
    20         cin >> a[i];
    21     stack<int> s;
    22     s.push(0);
    23     for (int i = 1; i <= n; ++i) {
    24         while (a[s.top()] > a[i])
    25             s.pop();
    26         l[i] = s.top();
    27         s.push(i);
    28     }
    29     stack<int> tmp;
    30     tmp.push(n + 1);
    31     for (int i = n; i > 0; --i) {
    32         while (a[tmp.top()] > a[i])
    33             tmp.pop();
    34         r[i] = tmp.top();
    35         tmp.push(i);
    36     }
    37     for (int i = 1; i <= n; ++i) {
    38         if ((i - l[i] - 1 >= x || l[i] == 0) && (r[i] - i - 1 >= y || r[i] == n + 1)) {
    39             cout << i << endl;
    40             return 0;
    41         }
    42     }
    43     return 0;
    44 }
    View Code

    B - Water Lily

    题意:离水面高H的花,走了L触及水面,问水深。

    分析:勾股定理。设答案为X,X*X+L*L=(X+H)*(X+H)。(cin和printf同用的不良风格)

     1 #include <bits/stdc++.h>
     2 
     3 #define maxn 100005
     4 #define mod 1000000007
     5 #define inf 0x3f3f3f3f
     6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     7 #define ll long long
     8 #define LL long long
     9 using namespace std;
    10 
    11 int main() {
    12     start;
    13     ll h, l;
    14     cin >> h >> l;
    15     printf("%.13lf",(l * l - h * h) * 1.0 / (2 * h));
    16     return 0;
    17 }
    View Code

    C - MP3

    题意:给定n个数,假设有K个不同的数,就要使用k=ceil(log2(K)) bits去存储每个数,总共需要n*k bits,一个大小为i bytes(1 byte=8 bits)的磁盘。对于一个区间[l,r]我们可以将小于l的数变成l,将大于r的数变成r,问最少变多少数使得磁盘能存下这些数。

    分析:能存i bytes,即能存8*i bits,则k=8*i/n,则K=2^(8*i/n),此即能存下的不同种类的数字(认为是l到r区间长度共有K,wa了一个小时,看到别人代码才发现),可表示为(1<<k)。

    (1)排序,可先找K个不同的数,然后滑动区间,左端点将所有等于左端点的数去掉,右端点加上右方下一组相等的数。同时要找最少的变化数,即找区间内最多的数。

     1 #include <bits/stdc++.h>
     2 
     3 #define maxn 400005
     4 #define mod 1000000007
     5 #define inf 0x3f3f3f3f
     6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     7 #define ll long long
     8 #define LL long long
     9 using namespace std;
    10 ll a[maxn];
    11 
    12 int main() {
    13     start;
    14     int n, I;
    15     cin >> n >> I;
    16     for (int i = 1; i <= n; ++i)
    17         cin >> a[i];
    18     sort(a + 1, a + n + 1);
    19     int sum = 0;
    20     int maxt = 0;
    21     ll k = 8 * I / n;
    22     if (k >= 30) {//(1<<30)>1e9
    23         cout << 0 << endl;
    24         return 0;
    25     }
    26     int K = (1 << k);
    27     int l = 1, r = 1;
    28     a[n + 1] = (1ll << 31);
    29     a[0] = -1;//两个哨兵
    30     int count = 1;
    31     for (; r <= n; ++r) {
    32         if (a[r] != a[r + 1]) {
    33             if (count == K)
    34                 break;
    35             ++count;
    36         }
    37     }
    38     if (r >= n) {//如果一整段区间都符合条件,且还可以存数,r会到n+1处
    39         cout << 0 << endl;
    40         return 0;
    41     }
    42     maxt = sum = r - l + 1;
    43     for (; l + maxt - 1 <= n;) {
    44         int t = l;
    45         for (; t <= n; ++t)
    46             if (a[t] != a[l])
    47                 break;
    48         if (t == n + 1)
    49             break;
    50         sum -= (t - l);
    51         l = t;
    52         ++r;
    53         ++sum;
    54         for (; r <= n; ++r) {
    55             if (a[r + 1] != a[r])
    56                 break;
    57             ++sum;
    58         }
    59         maxt = max(maxt, sum);
    60         if (r == n)
    61             break;
    62     }
    63     cout << n - maxt << endl;
    64     return 0;
    65 }
    View Code

    (2)排序,记录每一个相同的数有多少种,记为一组,然后找K组,然后滑动区间每次保证K组,找到区间内最多的数。

     1 #include <bits/stdc++.h>
     2 
     3 #define maxn 400005
     4 #define mod 1000000007
     5 #define inf 0x3f3f3f3f
     6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     7 #define ll long long
     8 #define LL long long
     9 using namespace std;
    10 ll a[maxn];
    11 
    12 int main() {
    13     start;
    14     int n, I;
    15     cin >> n >> I;
    16     for (int i = 1; i <= n; ++i)
    17         cin >> a[i];
    18     sort(a + 1, a + n + 1);
    19     ll k = 8 * I / n;
    20     if (k >= 30) {//(1<<30)>1e9
    21         cout << 0 << endl;
    22         return 0;
    23     }
    24     a[n + 1] = -1;//哨兵
    25     int K = (1 << k);
    26     vector<int> num;
    27     int cnt = 1;
    28     for (int i = 1; i <= n; ++i) {
    29         if (a[i] == a[i + 1])
    30             ++cnt;
    31         else {
    32             num.push_back(cnt);
    33             cnt = 1;
    34         }
    35     }
    36     if (num.size() < K) {
    37         cout << 0 << endl;
    38         return 0;
    39     }
    40     int sum = 0;
    41     int l = 0, r = K - 1;
    42     for (int i = 0; i <= r; ++i)
    43         sum += num[i];
    44     int maxt = sum;
    45     for (; r + 1 < num.size();) {
    46         sum -= num[l];
    47         ++l;
    48         ++r;
    49         sum += num[r];
    50         maxt = max(maxt, sum);
    51     }
    52     cout << n - maxt << endl;
    53     return 0;
    54 }
    View Code

    D - Welfare State

    题意:给n个数,有两种操作,第一种操作输入p和x,将第p个数变为x;第二种操作输入x,将所有小于x的数变成x。

    分析:对于a[i],最后的第一种操作一定是有效的,假设变为x,如果在该操作后出现了大于第二种操作输入的y,且y>x,则该数变成y。我们将q种操作编号为1~q。记录一个p[n]数组,一个t[n]数组,对于第i个数,p[i]表示最后的第一种操作,t[i]表示这个操作的编号。再记录一个maxi[n]数组,maxi[i]表示在第i个操作(包括第i个操作)之后的第二个操作变成的最大的数。

     1 #include <bits/stdc++.h>
     2 
     3 #define maxn 400005
     4 #define mod 1000000007
     5 #define inf 0x3f3f3f3f
     6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     7 #define ll long long
     8 #define LL long long
     9 using namespace std;
    10 ll a[maxn];
    11 ll p[maxn];
    12 ll t[maxn];
    13 ll maxi[maxn];
    14 
    15 int main() {
    16     start;
    17     memset(p, -1, sizeof(p));
    18     int n;
    19     cin >> n;
    20     for (int i = 1; i <= n; ++i)
    21         cin >> a[i];
    22     int q;
    23     cin >> q;
    24     for (int i = 0; i < q; ++i) {
    25         int x;
    26         cin >> x;
    27         if (x == 1) {
    28             int y, z;
    29             cin >> y >> z;
    30             p[y] = z;
    31             t[y] = i;
    32         } else {
    33             cin >> maxi[i];
    34         }
    35     }
    36     /*后缀操作,对于第i次操作,假设是第二种操作,如果后续有比该操作更大的值,则该操作可被后续操作覆盖*/
    37     /* 假设是第一种操作,假设后续有比该操作更大的第二次操作的值,同样可被覆盖*/
    38     for (int i = q - 2; i >= 0; --i)
    39         maxi[i] = max(maxi[i], maxi[i + 1]);
    40     for (int i = 1; i <= n; ++i) {
    41         int maxt = t[i];//a[i]最后进行第一次操作的编号
    42         if (p[i] == -1)//如果a[i]没有进行第一次操作,t[i]为0
    43             cout << max(a[i], maxi[maxt]) << ' ';//如果第0次操作后进行的第二种操作的x比a[i]大则输出x,反之亦反。
    44         else if (maxi[maxt] > p[i])//a[i]在最后一次(maxt次)第一种操作变成了x,在第maxt次后有一个第二种操作,该操作的值大于x,则输出该值
    45             cout << maxi[maxt] << ' ';
    46         else//第maxt操作将a[i]变成了p[i]且后续无有效操作
    47             cout << p[i] << ' ';
    48     }
    49     return 0;
    50 }
    View Code

    E和F我这种菜鸡估计是A不出来的。

     (如有问题,请在评论区和我说)

  • 相关阅读:
    NPOI开发手记
    jQuery.form开发手记
    jQuery.Flot开发手记
    node.js初探
    Linux私房菜阅读笔记
    c#实现常用排序算法
    Excel自定义函数开发手记
    浅谈知识管理
    Git学习手记
    c# 屏蔽快捷键
  • 原文地址:https://www.cnblogs.com/F-Mu/p/11278162.html
Copyright © 2020-2023  润新知