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";
}
}