• codeforces 576 div2 A-D题解


    A题

    Description

    • 题目链接: https://codeforces.com/contest/1199/problem/A
    • 题意:
    •   给定长度为n(1n100000)的一个序列a,以及两个整数x,y(0x,y7)。要求在序列里最靠前的一个索引d满足a[j]>=a[d] (dxj<d,d<j<d+y)。
    •   简单说就是找出一天使它的权值小于之前x天和之后y天,超出[1,n]的不考虑

    Solution

    • 思路:
    •   模拟从前往后遍历一遍,找到满足条件就输出。
     1 #include <bits/stdc++.h>
     2 #define lson rt << 1, l, mid
     3 #define rson rt << 1 | 1, mid + 1, r
     4 using namespace std;
     5 using ll = long long;
     6 using ull = unsigned long long;
     7 using pa = pair<int, int>;
     8 using ld = long double;
     9 int n, m, k;
    10 const int maxn = 1e6 + 10;
    11 template <class T>
    12 inline T read(T &ret)
    13 {
    14     int f = 1;
    15     ret = 0;
    16     char ch = getchar();
    17     while (!isdigit(ch))
    18     {
    19         if (ch == '-')
    20             f = -1;
    21         ch = getchar();
    22     }
    23     while (isdigit(ch))
    24     {
    25         ret = (ret << 1) + (ret << 3) + ch - '0';
    26         ch = getchar();
    27     }
    28     ret *= f;
    29     return ret;
    30 }
    31 template <class T>
    32 inline void write(T n)
    33 {
    34     if (n < 0)
    35     {
    36         putchar('-');
    37         n = -n;
    38     }
    39     if (n >= 10)
    40     {
    41         write(n / 10);
    42     }
    43     putchar(n % 10 + '0');
    44 }
    45 int a[maxn];
    46 int main(int argc, char const *argv[])
    47 {
    48     read(n);
    49     int x, y;
    50     read(x);
    51     read(y);
    52     for (int i = 1; i <= n; i++)
    53         read(a[i]);
    54     for (int i = 1; i <= n; i++)
    55     {
    56         int f = 1;
    57         for (int j = i - x; j > 0 && j < i; j++)
    58             if (a[j] <= a[i])
    59             {
    60                 f = 0;
    61                 break;
    62             }
    63         if (f)
    64         {
    65             for (int j = i + 1; j <= n && j <= i + y; j++)
    66                 if (a[j] <= a[i])
    67                 {
    68                     f = 0;
    69                     break;
    70                 }
    71         }
    72         if (f)
    73         {
    74             cout << i << "
    ";
    75             break;
    76         }
    77     }
    78     return 0;
    79 }
    View Code

    B题

    Description

    Solution:

    • 思路:
    •   勾股定理推出公式水面高H=(L2 - H2) / (2H) 
     1 #include <bits/stdc++.h>
     2 #define lson rt << 1, l, mid
     3 #define rson rt << 1 | 1, mid + 1, r
     4 using namespace std;
     5 using ll = long long;
     6 using ull = unsigned long long;
     7 using pa = pair<int, int>;
     8 using ld = long double;
     9 int n, m, k;
    10 const int maxn = 1e6 + 10;
    11 template <class T>
    12 inline T read(T &ret)
    13 {
    14     int f = 1;
    15     ret = 0;
    16     char ch = getchar();
    17     while (!isdigit(ch))
    18     {
    19         if (ch == '-')
    20             f = -1;
    21         ch = getchar();
    22     }
    23     while (isdigit(ch))
    24     {
    25         ret = (ret << 1) + (ret << 3) + ch - '0';
    26         ch = getchar();
    27     }
    28     ret *= f;
    29     return ret;
    30 }
    31 template <class T>
    32 inline void write(T n)
    33 {
    34     if (n < 0)
    35     {
    36         putchar('-');
    37         n = -n;
    38     }
    39     if (n >= 10)
    40     {
    41         write(n / 10);
    42     }
    43     putchar(n % 10 + '0');
    44 }
    45 int main(int argc, char const *argv[])
    46 {
    47     ios::sync_with_stdio(false);
    48     cin.tie(0);
    49     cout.tie(0);
    50     ld h, l;
    51     cin >> h >> l;
    52     ld ans = (l * l - h * h) / (h * 2);
    53     cout << fixed << setprecision(7) << ans << '
    ';
    54     return 0;
    55 }
    View Code

    C题

    Description

    • 题目链接: https://codeforces.com/contest/1199/problem/C
    • 题意:
    •   给一个长度为n的序列代表数字信号长度和一个I表示存储Ibyte,(1byte=8bit)。对于数字信号,每个信号需要花费k bits存储,k由序列内不同元素个数K决定,k=log2K向上取整,为了满足存储要求,我们可以将存储信号长度划定在一个区间[L,R]内
    •   小于L的变为L,大于R的变为R。问如何选取L,R使得改变的数字信号最少。输出最少改变次数。

    Solution:

    • 思路:
    •   阅读理解实锤了,看题看了半天没搞明白。首先我们可以将总共的字节数bits算出来,即8*I,用bits除以序列长度n得到每个数字信号的存储字节数m。这时候我们会发现2^m就是序列里的不同数字信号长度的上限,
    •   如果2^m≥序列长度n,那么肯定不用修改长度,此时答案为0。否则的话就需要我们对序列进行遍历判断了,我这里采用的是尺取法(?还是单调队列,我一直分不清,感觉差不多)。
    •   嗯还有就是在判断上限时不能采用直接取幂的方式,应该以对数来判断,不然存不下这个数会wa掉
    •   还wa了一个log,log是自然对数,log2才是2的对数,qaq
      1 //注意数据范围
      2 //log是自然对数 log2才是!!!
      3 #include <bits/stdc++.h>
      4 #define lson rt << 1, l, mid
      5 #define rson rt << 1 | 1, mid + 1, r
      6 using namespace std;
      7 using ll = long long;
      8 using ull = unsigned long long;
      9 using pa = pair<int, int>;
     10 using ld = long double;
     11 ll n, m, k;
     12 const int maxn = 4e5 + 10;
     13 const int inf = 0x3f3f3f3f;
     14 template <class T>
     15 inline T read(T &ret)
     16 {
     17     int f = 1;
     18     ret = 0;
     19     char ch = getchar();
     20     while (!isdigit(ch))
     21     {
     22         if (ch == '-')
     23             f = -1;
     24         ch = getchar();
     25     }
     26     while (isdigit(ch))
     27     {
     28         ret = (ret << 1) + (ret << 3) + ch - '0';
     29         ch = getchar();
     30     }
     31     ret *= f;
     32     return ret;
     33 }
     34 template <class T>
     35 inline void write(T n)
     36 {
     37     if (n < 0)
     38     {
     39         putchar('-');
     40         n = -n;
     41     }
     42     if (n >= 10)
     43     {
     44         write(n / 10);
     45     }
     46     putchar(n % 10 + '0');
     47 }
     48 vector<int> a(maxn);
     49 map<int, int> mp;
     50 set<int> s;
     51 struct node
     52 {
     53     int x, tot;
     54     node() {}
     55     node(int x, int tot)
     56     {
     57         this->x = x;
     58         this->tot = tot;
     59     }
     60 };
     61 int main(int argc, char const *argv[])
     62 {
     63     read(n);
     64     read(m);
     65     ll bits = m * 8; //总的字节数
     66     m = bits / n;    //一个元素可以占的字节数
     67     ld tmp = log2(n);
     68     for (int i = 0; i < n; i++)
     69     {
     70         read(a[i]);
     71         ++mp[a[i]];
     72         s.insert(a[i]);
     73     }
     74     ll ans = 0;
     75     if (m >= tmp)
     76     {
     77         write(0);
     78         putchar('
    ');
     79         return 0;
     80     }
     81     ull t = 1 << m;
     82     auto now = s.begin();
     83     ll cnt = 0;
     84     ull tot = 0;
     85     deque<int> dq;
     86     dq.clear();
     87     for (auto x : s)
     88     {
     89         ++tot;              //不同元素个数
     90         dq.emplace_back(x); //保存状态
     91         cnt += mp[x];       //不同元素总的个数
     92         if (tot > t)
     93         {
     94             if (!ans)
     95                 ans = inf;
     96             --tot;
     97             cnt -= mp[dq.front()];
     98             dq.pop_front();
     99             ans = min(n - cnt, ans);
    100         }
    101     }
    102     write(ans);
    103     return 0;
    104 }
    View Code

    D题

    Description:

    • 题目链接: https://codeforces.com/contest/1199/problem/D
    • 题意:
    •   给一个长为n的序列,q次操作,操作分为两种,一是将区间l,r内所有小于v的数改为v,二是将索引l位置的数改为x。q次操作后输出最后的序列。

    Solution:

    • 思路:
    •   赛场上t了,赛后重写了遍lazytag才过(哭了)。(感觉和前两天做的2018杭电多校有个题挺像,直接改了改交然后就t)
    •   回到主题,首先这个题区间操作,上线段树,区间修改加个懒标记,单点修改直接update,不过这个题在单点修改的时候需要将当前点的lazy标记清空,防止在查询答案时混淆。
      1 //线段树区间更新
      2 //对于单点,线段树维护下更新并将lazy赋值为0
      3 //对于区间,加上lazy标记
      4 #include <algorithm>
      5 #include <cstring>
      6 #include <iostream>
      7 #define lson rt << 1
      8 #define rson rt << 1 | 1
      9 using namespace std;
     10 using ll = long long;
     11 const int mod = 1 << 30;
     12 const int maxn = 2e5 + 10;
     13 int n, m;
     14 template <class T>
     15 inline T read(T &ret)
     16 {
     17     int f = 1;
     18     ret = 0;
     19     char ch = getchar();
     20     while (!isdigit(ch))
     21     {
     22         if (ch == '-')
     23             f = -1;
     24         ch = getchar();
     25     }
     26     while (isdigit(ch))
     27     {
     28         ret = (ret << 1) + (ret << 3) + ch - '0';
     29         ch = getchar();
     30     }
     31     ret *= f;
     32     return ret;
     33 }
     34 template <class T>
     35 inline void write(T n)
     36 {
     37     if (n < 0)
     38     {
     39         putchar('-');
     40         n = -n;
     41     }
     42     if (n >= 10)
     43     {
     44         write(n / 10);
     45     }
     46     putchar(n % 10 + '0');
     47 }
     48 struct node
     49 {
     50     int lazy, val, l, r;
     51 } tr[maxn << 2];
     52 int a[maxn];
     53 void pushdown(int rt)
     54 {
     55     if (tr[rt].lazy)
     56     {
     57         tr[lson].val = max(tr[lson].val, tr[rt].lazy);
     58         tr[rson].val = max(tr[rson].val, tr[rt].lazy);
     59         tr[lson].lazy = max(tr[rt].lazy, tr[lson].lazy);
     60         tr[rson].lazy = max(tr[rt].lazy, tr[rson].lazy);
     61         tr[rt].lazy = 0;
     62     }
     63 }
     64 void build(int rt, int l, int r)
     65 {
     66     tr[rt].l = l;
     67     tr[rt].r = r;
     68     tr[rt].lazy = 0;
     69     if (l == r)
     70     {
     71         read(tr[rt].val);
     72         a[l] = tr[rt].val;
     73         return;
     74     }
     75     int mid = l + r >> 1;
     76     build(rt << 1, l, mid);
     77     build(rt << 1 | 1, mid + 1, r);
     78 }
     79 void update(int rt, int L, int v)
     80 {
     81     int l = tr[rt].l;
     82     int r = tr[rt].r;
     83     if (l == r)
     84     {
     85         tr[rt].val = v;
     86         tr[rt].lazy = 0; //此题单点更新优先级大于懒标记
     87         return;
     88     }
     89     int mid = l + r >> 1;
     90     pushdown(rt); //没有返回代表不是完全包含于待查询区间,需要先下放懒标记再向左右区间查询
     91     if (L <= mid)
     92         update(rt << 1, L, v);
     93     else
     94         update(rt << 1 | 1, L, v);
     95 }
     96 void query(int rt, int L, int R)
     97 {
     98     int l = tr[rt].l;
     99     int r = tr[rt].r;
    100     if (l == r)
    101     {
    102         a[l] = max(tr[rt].val, tr[rt].lazy);
    103         return;
    104     }
    105     pushdown(rt); //同update
    106     int mid = l + r >> 1;
    107     if (L <= mid)
    108         query(rt << 1, L, R);
    109     if (R > mid)
    110         query(rt << 1 | 1, L, R);
    111 }
    112 int main(int argc, char const *argv[])
    113 {
    114     read(n);
    115     build(1, 1, n);
    116     read(m);
    117     for (int i = 0; i < m; i++)
    118     {
    119         int op, x, y;
    120         read(op);
    121         if (op == 1)
    122         {
    123             read(x);
    124             read(y);
    125             update(1, x, y);
    126         }
    127         else
    128         {
    129             read(x);
    130             tr[1].lazy = max(tr[1].lazy, x);
    131         }
    132     }
    133     query(1, 1, n);
    134     for (int i = 1; i <= n; i++)
    135     {
    136         write(a[i]);
    137         putchar(' ');
    138     }
    139     return 0;
    140 }
    View Code
  • 相关阅读:
    PAT 甲题 1155 Heap Paths
    PAT甲题 1014 Waiting in Line
    PAT甲题 1014 Waiting in Line
    AcWing 840. 模拟散列表
    2019新生赛 %%%xxh
    AcWing 240. 食物链
    AcWing 143. 最大异或对
    AcWing 838. 堆排序
    AcWing 836. 合并集合
    AcWing 837. 连通块中点的数量
  • 原文地址:https://www.cnblogs.com/mooleetzi/p/11276845.html
Copyright © 2020-2023  润新知