比赛链接:https://codeforc.es/contest/1199
A. City Day
题意:给出一个数列,和俩个整数\(x,y\),要求找到序号最靠前的数字\(d\),使得\(d\)满足\(a_d<a_j\) (\(d-x\leq j<d\) && \(d<j\leq d+y\))。
分析:由于x和y都小于7,所以直接暴力即可。
AC代码:
#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
ll n, x, y, a[SIZE];
int main() {
io();
cin >> n >> x >> y;
rep(i, 1, n) cin >> a[i];
rep(i, 1, n) {
bool flag = 1;
for (int k = i - 1, cnt = 1; k > 0 && cnt <= x; k--, cnt++) {
if (a[k] <= a[i]) { flag = 0; break; }
}
for (int k = i + 1, cnt = 1; k <= n && cnt <= y; k++, cnt++) {
if (a[k] <= a[i]) { flag = 0; break; }
}
if (flag) { cout << i << endl; return 0; }
}
}
B. Water Lily
分析:几何水题,推个方程就好。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
double l, h;
cin >> h >> l;
double s = (l * l - h * h) / 2 / h;;
printf("%.12lf", s);
}
C. MP3
题意:一个数组中如果有\(K\)种不同的数,每个数的占用空间是\(k=log_2K\),这组数总内存是\(nk\),你有一个改变数的大小的能力,小于\(l\)可以改成\(l\)大于\(r\)可以改成\(r\),现在给出总内存,求最少改变次数。
分析:先求出最多能存\(k\)个数,然后我们显然用\(map\)来记录数据,然后把\(map\)中的前\(k\)个数和后k个数丢进一个双向队列(因为我们至少删除\(k\)个数,而这\(k\)个数只能在首或尾),对这\(2k\)个数求前缀和,在每k个数中求出最小值。
AC代码:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define SIZE 400007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
ll n, I, a[SIZE], pre[SIZE];
map<ll, ll> mp;
deque<pair<ll, ll> > q;
int main() {
io(); cin >> n >> I;
rep(i, 1, n) {
cin >> a[i];
++mp[a[i]];
}
ll k = 0; I *= 8; //用k记录最多存储几个数
while (1ll * ceil(log2(mp.size() - k))* n > I) k++;
auto it = mp.begin();
auto itr = mp.rbegin();
rep(i, 1, k) {
q.push_back(make_pair(it->first, it->second));
q.push_front(make_pair(itr->first, itr->second));
it++, itr++;
}
auto itx = q.begin();
rep(i, 1, q.size()) pre[i] = pre[i - 1] + itx++->second;
ll sum = INF;
rep(i, k, 2 * k) sum = min(sum, pre[i] - pre[i - k]);
cout << sum;
}
D. Welfare State
题意:给定一个\(n\)个数的数列和两种操作。操作一是把序号为\(p\)的数字修改为\(x\),操作二是把所有小于\(x\)的数字修改为\(x\)。输出最终的数列。
分析:乍一看像线段树,但是会\(T\)(别问我怎么知道的),实际上直接乱搞就过了。我们发现对于第一种操作和第二种操作我们只需要考虑较大的那种,因此开两个数组,\(b\)数组保存操作一,\(maxx\)数组保存操作二,最后取\(max\)输出即可。
AC代码:
#include<bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
ll n, m, a[SIZE], b[SIZE], sig, maxx[SIZE], pos;
int main() {
io(); cin >> n;
rep(i, 1, n) cin >> a[i];
cin >> m;
rep(i, 1, m) {
cin >> sig;
if (sig == 1) {
cin >> pos;
cin >> a[pos];
b[pos] = i;
}
else cin >> maxx[i];
}
for (int i = m; i; --i) maxx[i - 1] = max(maxx[i - 1], maxx[i]);
rep(i, 1, n) cout << max(a[i], maxx[b[i]]) << ' ';
}
E. Matching vs Independent Set
题意: