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题太水的弥补???