Codeforces Round #679 (Div. 1, based on Technocup 2021 Elimination Round 1)题解

A.Perform Easily

题解:考虑枚举最小值,然后对于每个$b_i$,减去能使减后的值仍大于最小值的最大$a_i$,这么做的时间复杂度为$O(36n^2)$

我们发现枚举最小值后,并不需要遍历每个数,而只需要找到对于$k \in [1,6]$的

$$\max\{b_i-a_k\},minn+a_k\leq b_i<minn+a_{k+1}$$

用set维护即可$O(6 \log n)$找到最大值

总复杂度是$O(36n\log n)$

#include <bits/stdc++.h>
using namespace std;
int n, b[100011], a[7], minn, ans;
set <int> s;
int main() {
	for(int i = 1; i <= 6; i++) scanf("%d", &a[i]);
	scanf("%d", &n); minn = 2e9;
	for(int i = 1; i <= n; i++) {
		scanf("%d", &b[i]);
		minn = min(minn, b[i]);
		s.insert(b[i]);
	}
	sort(a+1, a+7); ans = 2e9;
	for(int i = 1; i <= n; i++)
	for(int j = 1; j <= 6; j++) {
		if(b[i] - a[j] > minn - a[1]) continue;
		int Min = b[i] - a[j], Max = 0;
		for(int k = 2; k <= 6; k++) {
			set<int>::iterator it = s.lower_bound(Min+a[k]); 
			if(it == s.begin()) continue;
			it--;
			Max = max(Max, *it - a[k-1]);
		}
		set<int>::iterator it = s.end(); it--;
		Max = max(Max, *it - a[6]);
		ans = min(ans, Max - Min);
	}
	printf("%d\n", ans);
	return 0;
}

 


B.Shurikens

翻译好评

题解:这题似乎比A还简单

我们倒序进行操作,维护一个栈

对于每个购买操作,我们把它压入栈中

对于每个放置操作,我们只需取出栈顶

如果当前压入栈中的数大于栈顶元素/弹栈时栈为空,则无解

考虑正确性:

栈中存储的是接下来要购买的物品价格(也即之前放置的物品),由于购买时一定买最便宜的,所以最便宜的最后加入一定是最优的

如果当前压入栈中的数大于栈顶元素,那么当前元素和栈顶元素都会在前面放入,不符合买最便宜的要求,无解

时间复杂度$O(n)$

#include <bits/stdc++.h>
using namespace std;
int n, sta[200011], cnt;
int s[200011], ans[200011];
char opt[200011];
int main() {
	scanf("%d", &n); n *= 2;
	for(int i = 1; i <= n; i++) {
		cin >> opt[i];
		if(opt[i] == '-') scanf("%d", &s[i]);
	}
	for(int i = n; i >= 1; i--) {
		if(opt[i] == '-') {
			if(cnt && s[i] > sta[cnt]) {
				cout << "NO" << endl;
				return 0;
			}
			sta[++cnt] = s[i];
		}
		else {
			if(!cnt) {
				cout << "NO" << endl;
				return 0;
			}
			ans[i] = sta[cnt--];
		}
	}
	cout << "YES" << endl;
	for(int i = 1; i <= n; i++) 
	if(opt[i] == '+') cout << ans[i] << " ";
	return 0;
}

 


C.Solo mid Oracle

我的数学真的太差了啊啊啊

推式子推错了,还不会算最大决策点,人没了

于是看了题解

 

题解:首先如果$a>b*c$,则答案为$-1$

我们先瞎jb推出来第$i$次施法的瞬间造成的总伤害,然后要找一个最大决策点

根据题解,这个最大贡献点是$\lfloor \dfrac{a-1}{b*d}+1 \rfloor$,于是就做完了

我原来还想三分做,发现会爆$\text{long long}$,其实应该可以写个高精过掉的,但是我懒得写了

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int t;
ll a, b, c, d, ans, sum;
ll calc(ll i) {
	sum = 0;
	ll tim = (i-1) * d + 1;
	sum = a * i; 
	sum -= b * c * i; 
	sum += b * i * (1 + c - tim) + b * d * (i - 1) * i / 2;
	return sum;
}
void solve() {
	scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
	if(b * c < a) {
		printf("-1\n");
		return;
	}
	ll answ = (a-1) / (b*d) + 1;
	printf("%lld\n", calc(answ));
}
int main() {
	scanf("%d", &t);
	while(t--) solve();
	return 0;
}

 所以这道题是对B题太水的弥补???

posted @ 2020-11-19 11:00  huangxuanao  阅读(145)  评论(0)    收藏  举报