A. Greedy Monocarp
题目大意
有N个箱子,第i个箱子里有Ai个硬币,有一个人会从多到少拿这些箱子。
现在你可以给一个箱子加若干硬币,请你使这个人可以拿到刚好K个硬币时停下拿箱子,要求加入的硬币数量尽量少。
解题思路
排个序,然后从大到小加,加到刚好不能再多加一个箱子为止,结果就是K-sum。
void solve()
{int n, k;cin >> n >> k;vi v(n);fore(i, v) cin >> i;sort(all(v));reverse(all(v));int sum = 0;rep(i, n) {sum += v[i];if (sum >= k) break;if (i != n - 1)if (sum < k && sum + v[i + 1] > k) {cout << k - sum << endl;return;}}cout << k - sum << endl;
}
B. Game with Colored Marbles
题目大意
两个人玩游戏,桌子上有N个不同颜色的弹珠,他们可以轮流选择弹珠拿走,最后拿完的时候记分,积分规则如下:
- 有一个不同颜色的弹珠加一分
- 完全拿完了一种颜色的弹珠加一分
两个人都采取最佳策略,问Alice最后的分数。
解题思路
对于单个的弹珠两个人肯定是轮流拿,剩下的弹珠Alice都能抢到一个。
int cnt[1005];
void solve()
{int n;cin >> n;vi v(n);memset(cnt, 0, sizeof(cnt));fore(i, v) {cin >> i;cnt[i]++;}int cnt1 = 0, cnt2 = 0;repo(i, 1000) {if (cnt[i] == 1) cnt1++;else if (cnt[i] != 0) cnt2++;}int ans = (cnt1 + 1) / 2 * 2 + cnt2;cout << ans << endl;
}
C. Competitive Fishing
题目大意
有一个序列,0表示Alice,1表示Bob,你可以把整个序列分成m段,对于第一段的积分为0,第二段积分为1,第三段积分为3...,两个人分别根据01在哪个段内加分。
现在Bob想领先Alice至少k分,问最少要分多少段(分段方式自选)
解题思路
考虑在某个位置划一刀带来的贡献,贡献就是后缀所有的位置的积分都会+1,那么Bob领先的差值就会增加后缀1的个数减去后缀0的个数。
那么对于每个位置都计算一下后缀1的个数减去0的个数,然后排个序算最少要划几刀就可以了。
int cnt[1005];
void solve()
{int n;cin >> n;vi v(n);memset(cnt, 0, sizeof(cnt));fore(i, v) {cin >> i;cnt[i]++;}int cnt1 = 0, cnt2 = 0;repo(i, 1000) {if (cnt[i] == 1) cnt1++;else if (cnt[i] != 0) cnt2++;}int ans = (cnt1 + 1) / 2 * 2 + cnt2;cout << ans << endl;
}
D. Recommendations
题目大意
有N个区间,一个区间如果完全包含另一个区间,那么就被称作是这个区间的predictor,求每个区间的所有predictor的相同覆盖段长度。
解题思路
显然相同覆盖段长度是这些predictor的最小的R-最大的L,那么就是一个二维数点,求以LR为XY轴的二维平面内,左上角的区域中最小的R和最大的L。
代码从X轴扫的,其实扫Y轴更方便。
const int m = 1e9 + 2;int n, s[200005];struct su {int x, y, id;bool operator<(const su& temp)const {if (x == temp.x) return y > temp.y;return x < temp.x;}
}a[200005];
int ans[200005];void add(int x, int v) {for (;x <= n;x += x & -x) s[x] = max(s[x], v);
}int ask(int x) {int res = 0;for (;x;x -= x & -x) res = max(s[x], res);return res;
}void solve()
{cin >> n;set<int> q;vector<int> f;unordered_map<int, int> mp;for (int i = 1;i <= n;++i) {int x, y;cin >> x >> y;a[i].x = x;a[i].y = y;a[i].id = i;f.push_back(a[i].y);s[i] = 0;}sort(all(f));reverse(all(f));unique(all(f));for (int i = 0;i < f.size();++i) {if (i > 0 && (f[i] > f[i - 1])) break;mp[f[i]] = i + 1;}sort(a + 1, a + n + 1);repo(i, n) {if (i > 1) {q.insert(a[i - 1].y);add(mp[a[i - 1].y], a[i - 1].x);}if ((i > 1 && a[i].x == a[i - 1].x && a[i].y == a[i - 1].y) || (i < n && a[i].x == a[i + 1].x && a[i].y == a[i + 1].y)) {ans[a[i].id] = 0;continue;}auto xx = q.lower_bound(a[i].y);if (xx == q.end()) {ans[a[i].id] = 0;continue;}int y = ask(mp[a[i].y]);if (y == 0 || (*xx) < y) {ans[a[i].id] = 0;continue;}ans[a[i].id] = (*xx) - y - (a[i].y - a[i].x);}repo(i, n) {cout << ans[i] << "\n";}
}