251021cch模拟赛总结

· · 个人记录

100 + 100 + 100 + 30 = 330

## A - makise $30min$才过,我太菜了 首先只有奇数会有贡献,而且操作完之后都是偶数,所以每次先手操作的时候都会选两个奇数,让它们不产生贡献 后手因为先手操作之后一定能有偶数,所以会用一奇一偶产生$1$的贡献 然后就可以做了 ```cpp #include <bits/stdc++.h> #define LL long long using namespace std; LL n; int main () { // freopen("makise.in", "r", stdin); // freopen("makise.out", "w", stdout); ios::sync_with_stdio(0), cin.tie(0); cin >> n; LL s = 0, sum = 0; for (LL i = 1, x; i <= n; i++) { cin >> x; s += x & 1; sum += x; if (i == 1) { cout << x << ' '; continue; } LL tmp = s / 3, tmp1 = s % 3; if (tmp1 != 1) { cout << sum - tmp << ' '; continue; } cout << sum - tmp - 1 << ' '; } return 0; } ``` ## B - shop 我居然能在考场上写出贪心:) 首先我们发现,用$a$的限制是只能用一次,用$b$的限制是必须用了它对应的$a

然后想到b一定是反复的用同一个,所以考虑枚举这个b,那么a就只会贪心的选比这个b大的,和这个b对应的a

然后大样例就WA了,应为n会比m小,就把ans初始化一下,然后枚举b的时候如果要选的an多就跳过

#include <bits/stdc++.h>
#define LL long long

using namespace std;

const int N = 3e5 + 5;

LL t, n, m, aa[N], s[N];
struct zs {
  LL a, b;
} a[N];

bool cmp (zs x, zs y) {
  return x.b > y.b;
}

int main () {
  // freopen("shop.in", "r", stdin);
  // freopen("shop.out", "w", stdout);
  ios::sync_with_stdio(0), cin.tie(0);
  for (cin >> t; t--;) {
    cin >> m >> n;
    for (int i = 1; i <= n; i++) {
      cin >> a[i].a >> a[i].b;
      aa[i] = a[i].a;
    }
    sort(a + 1, a + n + 1, cmp);
    sort(aa + 1, aa + n + 1);
    s[n + 1] = 0;
    for (int i = n; i >= 1; i--) {
      s[i] = s[i + 1] + aa[i];
    }
    LL ans = s[max(0ll, n - m + 1)];
    for (int i = 1; i <= n; i++) {
      LL k = lower_bound(aa + 1, aa + n + 1, a[i].b) - aa;
      if (k <= n - m + 1) continue;
      ans = max(ans, s[k] + (a[i].a >= a[i].b ? a[i].b * (m - (n - k + 1)) : a[i].a + a[i].b * (m - (n - k + 2))));
    }
    cout << ans << '\n';
  }
  return 0;
}

C - divide

卡掉人类智慧!!!卡掉人类智慧!!!卡掉人类智慧!!!卡掉人类智慧!!!卡掉人类智慧!!!卡掉人类智慧!!!

卡掉人类祝睿

看完题第一反应是dp,设f[i]表示1-i的答案

转移:f[i] = max_{j = 0}^{i - 1}{f[j] + v(j + 1, i)}

然后想到线段树优化$dp$,单点修改,区间查询,$i$每次往右一个,就把它到它前面第一个比它小的位置到它的$v$改成它 可以用单调栈处理出在每个数前面的第一个比它小的位置 然后就好做了:) 然而有人的人类智慧过了!qwq 卡掉他们qwq 真的卡掉了!!好耶:) ```cpp #include <bits/stdc++.h> #define LL long long #define ls k << 1 #define rs k << 1 | 1 using namespace std; const LL N = 1e5 + 5, inf = 1e18; LL n, f[N], nxt[N], s[N], t; struct aa { LL a, b; } a[N]; struct node { LL mx, mxf, tag; } tree[N * 4]; void push_down (int k) { if (tree[k].tag == -inf) return; tree[ls].mx = tree[ls].mxf + tree[k].tag; tree[rs].mx = tree[rs].mxf + tree[k].tag; tree[ls].tag = tree[k].tag; tree[rs].tag = tree[k].tag; tree[k].tag = -inf; } void push_up (int k) { tree[k].mx = max(tree[ls].mx, tree[rs].mx); tree[k].mxf = max(tree[ls].mxf, tree[rs].mxf); } void update1 (int k, int l, int r, int l1, int r1, LL x) { if (l >= l1 && r <= r1) { tree[k].mx = tree[k].mxf + x; tree[k].tag = x; return; } push_down(k); int mid = l + r >> 1; if (mid >= l1) { update1(ls, l, mid, l1, r1, x); } if (mid < r1) { update1(rs, mid + 1, r, l1, r1, x); } push_up(k); } void build (int k, int l, int r) { tree[k].mx = tree[k].mxf = tree[k].tag = -inf; if (l == r) return; int mid = l + r >> 1; build(ls, l, mid); build(rs, mid + 1, r); } LL query (int k, int l, int r, int l1, int r1) { if (l >= l1 && r <= r1) { return tree[k].mx; } push_down(k); LL mid = l + r >> 1, ret = -inf; if (mid >= l1) { ret = query(ls, l, mid, l1, r1); } if (mid < r1) { ret = max(ret, query(rs, mid + 1, r, l1, r1)); } return ret; } void update2 (int k, int l, int r, int k1, LL x) { if (l == r) { tree[k].mxf = x; tree[k].mx += x; return; } push_down(k); int mid = l + r >> 1; if (mid >= k1) { update2(ls, l, mid, k1, x); } else { update2(rs, mid + 1, r, k1, x); } push_up(k); } int main () { // freopen("divide.in", "r", stdin); // freopen("divide.out", "w", stdout); ios::sync_with_stdio(0), cin.tie(0); cin >> n; for (int i = 1; i <= n; i++) { cin >> a[i].a; } for (int i = 1; i <= n; i++) { cin >> a[i].b; } s[t = 1] = 0; for (int i = 1; i <= n; i++) { for (; a[s[t]].a > a[i].a; t--); nxt[i] = s[t]; s[++t] = i; } build(1, 1, n); update2(1, 1, n, 1, 0); fill(f + 1, f + n + 1, -inf); for (int i = 1; i <= n; i++) { update1(1, 1, n, nxt[i] + 1, i, a[i].b); f[i] = query(1, 1, n, 1, i); if (i == n) break; update2(1, 1, n, i + 1, f[i]); } cout << f[n]; return 0; } /* yang li tai shui le zhe me shit dou neng guo */ ``` ## D - tree cch果然喜欢tree 还剩$2h$,~~心态直接崩飞~~ 想过了树形$dp$,换根,淀粉质,树剖,最终决定打暴力:) 赛后看到hhc的正解是我不会的算法,题解的长链剖分我也不会:) 炸掉了:) ```cpp #include <bits/stdc++.h> #define LL long long using namespace std; const int N = 1e5 + 5; LL n, ans; vector <LL> v[N], f[N]; void dfs1 (int x, int fa) { f[x].emplace_back(v[x].size() - (x != 1)); for (int i : v[x]) { if (i == fa) continue; dfs1(i, x); for (int j = 0; j < f[i].size(); j++) { if (f[x].size() <= j + 1) { f[x].emplace_back(f[i][j]); } else { f[x][j + 1] += f[i][j]; } } } } void qwq (int x, int y) { for (int i = 0; i < min(f[x].size(), f[y].size() + 1); i++) { if (i == 0) { f[x][i]--; } else { f[x][i] -= f[y][i - 1]; } } for (int i = 0; i < f[x].size(); i++) { if (f[y].size() <= i + 1) { f[y].emplace_back(f[x][i]); } else { f[y][i + 1] += f[x][i]; } } if (!f[y].size()) f[y].emplace_back(0); f[y][0]++; } void dfs2 (int x, int fa) { if (v[x].size() >= 3) { ans += 1ll * v[x].size() * (v[x].size() - 1) * (v[x].size() - 2) / 6; // cout << ans << '\n'; for (int i = 0; i < f[x].size(); i++) { LL s = 0, s1 = 0; for (int j : v[x]) { if (f[j].size() <= i) continue; ans += f[j][i] * s1; s1 += f[j][i] * s; s += f[j][i]; // cout << ans << ' ' << s << ' ' << s1 << ' ' << f[j][i] << ' ' << j << ' ' << i << '\n'; } } } // cout << x << '\n'; // for (int i : f[x]) { // cout << i << ' '; // } // cout << '\n'; // for (int i : v[x]) { // for (int j : f[i]) { // cout << j << ' '; // } // cout << '\n'; // } // cout << ' ' << ans << '\n'; for (int i : v[x]) { if (i == fa) continue; qwq(x, i); dfs2(i, x); qwq(i, x); } } int main () { // freopen("tree.in", "r", stdin); // freopen("tree.out", "w", stdout); ios::sync_with_stdio(0), cin.tie(0); cin >> n; for (int i = 1, x, y; i < n; i++) { cin >> x >> y; v[x].emplace_back(y); v[y].emplace_back(x); } dfs1(1, 1); dfs2(1, 1); cout << ans; return 0; } /* xiao yang li zhe me shui a qwq zen me xie dou neng guo zi ji zao de dou guo bu liao , ran hou xiao yang li hai guo le tai ** nan tiao le qwq */ ``` ## 前3题写的非常顺利,但是T4是没学过的东西,相当于$2h$没事做qwq