题解:P12370 [蓝桥杯 2022 省 Python B] 技能升级
P12370 [蓝桥杯 2022 省 Python B] 技能升级
题意分析
一共有
思路
首先贪心,很容易想到每次加最大值是最优解,欸那这不就是单点修改,区间查询吗,直接线段树…等等
如果我们把每个 逃)。
那么经过操作之后,大概会变成这样。
仔细观察这个图,就能发现操作结束后 现在你知道标签里为啥有二分了吧)。对这个值二分,计算每个
#include<bits/stdc++.h>
using namespace std;
long long n, m, a[100005], b[100005], c[100005], maxn, l, r, x, tot, ans, cnt, mid;
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++) {
cin >> a[i] >> b[i];
maxn = max(maxn, a[i]);//记录最大值
}
l = 0, r = maxn;
while(l <= r) {
tot = 0;
x = (l + r) / 2;
for(int i = 1; i <= n; i++) {
if(a[i] >= x) tot += (a[i] - x) / b[i] + 1;
}
if(tot >= m) l = x + 1, mid = x;
else r = x - 1;
}//二分查找
tot = 0;
for(int i = 1; i <= n; i++) {
if(a[i] >= mid) {
cnt = (a[i] - mid) / b[i] + 1;
tot += cnt;
ans += (a[i] * 2 - (cnt - 1) * b[i]) * cnt / 2;
a[i] -= (cnt-1) * b[i];
c[i] = a[i];
}
}//贪心加和
sort(c+1, c+1+n);
int j = 1;
for(int i = 1; i <= tot - m; i++) {
if(j > n) break;
if(c[j] == 0) {j++, i--; continue;}
ans -= c[j];
}//修改
cout << ans;
return 0;
}
无耻求赞。