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 << "\n";
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 << '\n';
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('\n');
 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

 

posted @ 2019-07-31 15:51  mool  阅读(211)  评论(0编辑  收藏  举报