codeforces 576 div2 A-D题解
A题
Description
- 题目链接: https://codeforces.com/contest/1199/problem/A
- 题意:
- 给定长度为n(1≤n≤100000)的一个序列a,以及两个整数x,y(0≤x,y≤7)。要求在序列里最靠前的一个索引d满足a[j]>=a[d] (d−x≤j<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 }
Description
- 思路:
- 勾股定理推出公式水面高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 }
Description
Solution:
- 答案为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 }
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 }