https://ac.nowcoder.com/acm/contest/10507
C - 宝石街
题意:给定一个数组,从左往右走,每次可以拿不超过 a[i] 个宝石或扔掉任意个宝石,设在某点拥有宝石总数为 k,则到达下一点需要时间也是 k,问在 t 时间内,最多拿多少个宝石,不需要到终点。
尺取法
如果最终停在 i 点,则 ai 必定都拿,ai−1 也是尽量多拿,ai−2 也是,以此类推。
所以对于每点,需要算出最左从哪点开始拿。可以知道这个点是随着 i 而递增的。
所以尺取,或者双指针。
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,b 删掉,并加入 a×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; }
|