https://ac.nowcoder.com/acm/contest/10507

C - 宝石街

 

题意:给定一个数组,从左往右走,每次可以拿不超过 a[i]a[i] 个宝石或扔掉任意个宝石,设在某点拥有宝石总数为 kk,则到达下一点需要时间也是 kk,问在 tt 时间内,最多拿多少个宝石,不需要到终点。

尺取法

如果最终停在 ii 点,则 aia_i 必定都拿,ai1a_{i-1} 也是尽量多拿,ai2a_{i-2} 也是,以此类推。

所以对于每点,需要算出最左从哪点开始拿。可以知道这个点是随着 ii 而递增的。

所以尺取,或者双指针。

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
#include <bits/stdc++.h>
#define debug(x) cout << #x << ":\t" << (x) << endl;
using namespace std;
#define ll long long
#define ull unsigned ll
const int N = 6e7 + 10;
const int INF = 0x3f3f3f3f;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
int n;
ll t;
ll a[N];
int type;
ll sum[N], ans;
int main() {
scanf("%d%lld%d", &n, &t, &type);
if (type == 1) {
for (int i = 1; i <= n; i++)scanf("%lld", &a[i]);
}
else {
ll p;
scanf("%lld%lld", &a[1], &p);
for (int i = 2; i <= n; i++) {
ll x = (a[i - 1] ^ (a[i - 1] << 13));
ll y = (x ^ (x >> 17));
a[i] = (y ^ (y << 5)) % p + 1;
}
}
for (int i = 1; i <= n; i++)sum[i] = sum[i - 1] + a[i];
int L1 = 1, L2 = 1;
ll rs = 0, tot = 0;
ans = a[1];
ll pre = a[1];
for (int i = 2; i <= n; i++) {
tot += sum[i - 1] - sum[L2 - 1] + rs;
ll tmp = pre + a[i];
if (tot <= t) {
pre = tmp;
ans = max(ans, tmp);
continue;
}
if (tot - rs * (i - L1) <= t) {
tot -= rs * (i - L1);
ll nrs = (t - tot) / (i - L1);
tmp = tmp - rs + nrs;
tot = tot + nrs * (i - L1);
rs = nrs;
if (rs == 0)L1 = L2;
pre = tmp;
ans = max(ans, tmp);
continue;
}
tmp -= rs;
tot -= rs * (i - L1);
while (tot > t) {
tot -= a[L2] * (i - L2);
tmp -= a[L2];
L2++;
}
rs = (t - tot) / (i - L2 + 1);
tot += rs * (i - L2 + 1);
tmp += rs;
if (rs > 0)L1 = L2 - 1;
else L1 = L2;
pre = tmp;
ans = max(ans, tmp);
}
printf("%lld\n", ans);
return 0;
}

 

D - 减数游戏

 

题意:给定一个数列,每次任选两个数 a,ba,b 删掉,并加入 a×b+ka\times b+k,问最终剩下的数最大是几。

贪心+思维

贪心的部分在于:每次选择最小的两个数,再把新数加入数列后继续。

但是这样数字越来越大,会爆ll,就没法比大小了。

关键在于,如果当前最小的两个数组成的新数大于等于最大的数,也就是新数成为了数列中新的最大的数,那么以后每次都必定会产生新的最大的数。证明显然。

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
#include <bits/stdc++.h>
#define debug(x) cout << #x << ":\t" << (x) << endl;
using namespace std;
#define ll long long
#define ull unsigned ll
const int N = 2e6 + 10;
const int INF = 0x3f3f3f3f;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
int n;
ll k;
ll a[N], mx;
priority_queue<ll, vector<ll>, greater<ll> >q;
deque<ll>dq;
int main() {
scanf("%d%lld", &n, &k);
for (int i = 1; i <= n; i++)scanf("%lld", &a[i]), q.push(a[i]), mx = max(mx, a[i]);
while (q.size() > 1 && q.top() < mx) {
ll x = q.top(); q.pop();
ll y = q.top(); q.pop();
q.push(x*y + k);
}
while (!q.empty()) {
dq.push_back(q.top() % mod); q.pop();
}
while (dq.size() > 1) {
ll x = dq.front(); dq.pop_front();
ll y = dq.front(); dq.pop_front();
dq.push_back((x*y + k) % mod);
}
printf("%lld\n", dq.front());
return 0;
}