Codeforces Round #727 (Div. 2)

\(\sf D-PriceFixed\)

题目

简要题意

在一个折扣店有 \(n\) 种商品,每种商品的价格都是 \(2\)。对于商品 \(i\) 你需要买 \(a_i\) 个,而如果在买商品 \(i\) 之前你购买的商品数量(指所有种类的商品数量)大于等于 \(b_i\),你就可以半价购买商品 \(i\)

请合理安排商品购买顺序使得完成购买任务所花费的钱最少。

数据范围与提示

\(n\le 1e5,\ 1\le a_i,b_i\le 10^{14}\)

解法

#1. \(\text{Two Pointers}\)

贪心地想,在当前 \(b_i\) 最小的商品不能半价时买 \(b_i\) 最大的商品一定不会更劣。

所以可以直接将商品按 \(b_i\) 排序,用两个指针 \(l,r\) 往中间遍历。我们用牺牲 \(r\) 换取 \(l\) 的半价。

#2. \(\text{Binary Search}\)

我们还是将商品按 \(b_i\) 排序。那么任务就是最小化全价商品数。

二分全价商品数 \(\rm mid\)。检验是否合法就是按排序顺序遍历商品,购买能够买到的所有半价商品数记其为 \(w\),如果满足 \(\text{mid}+w\ge \sum a_i\) 就合法。

时间复杂度 \(\mathcal O(n\log 10^{14})\)

代码

#1. \(\text{Two Pointers}\)

#include <bits/stdc++.h>
using namespace std;

#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define print(x,y) write(x),putchar(y) 

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>‘9‘||s<‘0‘) if(s==‘-‘) f=-1;
    while(s>=‘0‘&&s<=‘9‘) x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar(‘-‘),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}

typedef long long ll;
typedef pair <ll,ll> Pair;

const int maxn=1e5+5;

int n;
Pair s[maxn];

int main() {
	n=read(9);
	rep(i,1,n) s[i].second=read(9ll),s[i].first=read(9ll);
	sort(s+1,s+n+1);
	ll ans=0,sum=0; int l=1,r=n;
	while(l<r) {
		if(sum<s[l].first) {
			if(s[r].second>s[l].first-sum) {
				s[r].second-=s[l].first-sum;
				ans+=(s[l].first-sum)*2,sum=s[l].first;
			}
			else {
				sum+=s[r].second;
				ans+=s[r].second*2; s[r].second=0,--r;
			}
			if(sum>=s[l].first) {
				sum+=s[l].second,ans+=s[l].second,++l;
			}
		}
		else sum+=s[l].second,ans+=s[l].second,++l;
	}
	if(l==r) {
		if(sum>=s[l].first) ans+=s[l].second;
		else {
			if(s[l].second>s[l].first-sum)
				ans+=(s[l].first-sum)*2+s[l].second-s[l].first+sum;
			else ans+=s[l].second*2;
		}
	}
	print(ans,‘\n‘);
	return 0;
} 

#2. \(\text{Binary Search}\)

#include <bits/stdc++.h>
using namespace std;

bool cmp(pair<long long, long long> &x, pair<long long, long long> &y) {
    return x.second < y.second;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n; cin >> n;
    vector<pair<long long, long long>> in(n);
    for(int i = 0; i < n; i++) {
        cin >> in[i].first >> in[i].second;
    }
    sort(in.begin(), in.end(), cmp);

    long long lo = 0LL, hi = 1e15, tot = 0LL;
    for(int i = 0; i < n; i++) {
        tot += in[i].first;
    }
    for(int j = 0; j < 60; j++) {
        long long tst = (lo + hi) / 2;
        long long soFar = tst;
        for(int i = 0; i < n; i++) {
            if(soFar >= in[i].second)
                soFar += in[i].first;
        }
        if(soFar >= tot) {
            hi = tst;
        }
        else lo = tst + 1;
    }
    cout << tot + lo << "\n";
}

Codeforces Round #727 (Div. 2)

上一篇:torch.randn()说明


下一篇:性能工具之locust工具get与post请求