Codeforces Round #727 (Div. 2)

(sf D-PriceFixed)

题目

简要题意

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

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

数据范围与提示

(nle 1e5, 1le a_i,b_ile 10^{14})

解法

#1. ( ext{Two Pointers})

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

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

#2. ( ext{Binary Search})

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

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

时间复杂度 (mathcal O(nlog 10^{14}))

代码

#1. ( ext{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,'
');
	return 0;
} 

#2. ( ext{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 << "
";
}
原文地址:https://www.cnblogs.com/AWhiteWall/p/14916158.html