CF1728 ERed-Black Pepper

CF1728ERed-Black Pepper

题目描述

Monocarp is going to host a party for his friends. He prepared nn dishes and is about to serve them. First, he has to add some powdered pepper to each of them — otherwise, the dishes will be pretty tasteless.

The ii-th dish has two values aia_i and bib_i — its tastiness with red pepper added or black pepper added, respectively. Monocarp won’t add both peppers to any dish, won’t add any pepper multiple times, and won’t leave any dish without the pepper added.

Before adding the pepper, Monocarp should first purchase the said pepper in some shop. There are mm shops in his local area. The jj-th of them has packages of red pepper sufficient for xjx_j servings and packages of black pepper sufficient for yjy_j servings.

Monocarp goes to exactly one shop, purchases multiple (possibly, zero) packages of each pepper in such a way that each dish will get the pepper added once, and no pepper is left. More formally, if he purchases xx red pepper packages and yy black pepper packages, then xx and yy should be non-negative and xxj+yyjx \cdot x_j + y \cdot y_j should be equal to nn .

For each shop, determine the maximum total tastiness of the dishes after Monocarp buys pepper packages only in this shop and adds the pepper to the dishes. If it’s impossible to purchase the packages in the said way, print -1.

输入格式

The first line contains a single integer nn ( 1n31051 \le n \le 3 \cdot 10^5 ) — the number of dishes.

The ii -th of the next nn lines contains two integers aia_i and bib_i ( 1ai,bi1091 \le a_i, b_i \le 10^9 ) — the tastiness of the $i $-th dish with red pepper added or black pepper added, respectively.

The next line contains a single integer $m $( 1m31051 \le m \le 3 \cdot 10^5 ) — the number of shops.

The jj-th of the next mm lines contains two integers xjx_j and yjy_j ( 1xj,yjn1 \le x_j, y_j \le n ) — the number of servings the red and the black pepper packages are sufficient for in the jj -th shop, respectively.

输出格式

Print mm integers. For each shop, print the maximum total tastiness of the dishes after Monocarp buys pepper packages only in this shop and adds the pepper to the dishes. If it’s impossible to purchase the packages so that each dish will get the pepper added once and no pepper is left, print -1.

题目翻译

有n道菜, 对于第i道菜加入一份a佐料有a[i]a[i]的价值,加入一份b有b[i]b[i]的价值,每道菜只能加入一份佐料。现在有m个商店,每个商店都按瓶售卖佐料,一个瓶中只能有佐料a或者佐料b,一瓶佐料a有x份,一瓶佐料佐料b有y份,购买的佐料必须完全用完。求分别在每个商店购买佐料能获得价值的最大值,如果不能输出-1。

题目分析

对每个商店一眼就能列出不定方程组ax+by=nax+by=n,如果有解,有 axa*x 的通解:xa0+lcm(x,y)kx*a_0+lcm(x,y)*k,那么可以算出来 axa*x 的取值在一个范围,而且间隔都是lcm,那么先预处理出来选择i道菜加入佐料a,n-i道菜加入佐料b的最大价值,可以发现,选择i道菜加入佐料a的价值肯定是个单峰函数,而axa*x的取值范围也已知,那么可以通过二分求解,或者直接判断在峰两侧的值和取值范围两端的最大值。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <bits/stdc++.h>

using ll = long long;

long long exgcd(long long a, long long b, long long &x, long long &y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, x, y);
ll t = x;
x = y;
y = t - a / b * x;
return d;
}

void sol() {
int n;
std::cin >> n;
std::vector<int> diff(n);
long long sum = 0;
for (int i = 0; i < n; ++i) {
int a, b;
std::cin >> a >> b;
diff[i] = a - b;
sum += b;
}
std::sort(diff.begin(), diff.end(), std::greater());
std::vector<long long> pref(n + 1);
for (int i = 1; i <= n; ++i)pref[i] = pref[i - 1] + diff[i - 1];
long long big = std::max_element(pref.begin(), pref.end()) - pref.begin();

int m;
std::cin >> m;
while (m--) {
int x, y;
std::cin >> x >> y;

long long a, b;
long long g = exgcd(x, y, a, b);
if (n % g) {
std::cout << -1 << "\n";
continue;
}
a = a * (n / g) % (y / g);
if (a < 0) a += y / g;

if (1LL * x * a > n) {
std::cout << -1 << "\n";
continue;
}

long long lcm = x * y / g;
long long lef = x * a;
long long rig = n - (n - x * a) % lcm;

long long ans = std::max(pref[lef], pref[rig]);
if (big >= lef && big <= rig) {
int l = big - (big - lef) % lcm;
int r = big + (rig - big) % lcm;
ans = std::max({ans, pref[l], pref[r]});
}
std::cout << ans + sum << "\n";
}
}

int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif
#ifndef LOCAL
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
#endif
sol();
return 0;
}

CF1728 ERed-Black Pepper
https://mrxyan6.github.io/2022/09/09/CF1728E/
作者
mrx
发布于
2022年9月9日
许可协议