9.16训练赛
A. P7482 不条理狂诗曲
分治,详见代码。
#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
#define f first
#define s second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
const ll N = 1e5 + 1, M = 1e9 + 7;
ll t, n, m;
ll a, b, c, d;
ll x[N], ans;
ll ml[N], nl[N], mr[N], nr[N], sm[N], sn[N];
pll p[N];
inline bool lt(const pll &a, const pll &b) {
return a.f - a.s < b.f - b.s;
}
inline void cal(ll l, ll r) {
if (l == r)
return ans += x[l], void();
ll m = l + r >> 1;
cal(l, m), cal(m + 1, r); //在中点两侧的子区间递归计算
ml[m] = x[m], ml[m + 1] = 0;
fd(i, m - 1, l) ml[i] = max(ml[i + 1], ml[i + 2] + x[i]); //选取中点,往左dp
mr[m + 1] = 0, mr[m + 2] = x[m + 2];
fu(i, m + 3, r) mr[i] = max(mr[i - 1], mr[i - 2] + x[i]); //选取中点,往右dp
nl[m] = 0, nl[m - 1] = x[m - 1];
fd(i, m - 2, l) nl[i] = max(nl[i + 1], nl[i + 2] + x[i]); //不选中点,往左dp
nr[m] = 0, nr[m + 1] = x[m + 1];
fu(i, m + 2, r) nr[i] = max(nr[i - 1], nr[i - 2] + x[i]); //不选中点,往右dp
//计算跨过中点的子区间
//f(l,r) = max(ml[l] + mr[r], nl[l] + nr[r])
//如果 ml[l] + mr[r] < nl[l] + nr[r]
//则 ml[l] - nl[l] < nr[r] - mr[r]
//那么对左端点按ml[l] - nl[l]排序即可nlogn得到答案
c = 0;
// debug用
// fu(i, l, m) fu(j, m + 1, r) ans += max(ml[i] + mr[j], nl[i] + nr[j]);
fu(i, l, m) p[++c] = {ml[i], nl[i]};
sort(p + 1, p + c + 1, lt);
fu(i, 1, c) sm[i] = sm[i - 1] + p[i].f, sn[i] = sn[i - 1] + p[i].s;
fu(i, m + 1, r) {
ll pos = upper_bound(p + 1, p + c + 1, pll{nr[i], mr[i]}, lt) - p - 1;
ans += sm[c] - sm[pos] + mr[i] * (c - pos);
ans += sn[pos] + nr[i] * pos;
ans %= M;
}
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
fu(i, 1, n) cin >> x[i];
cal(1, n);
cout << ans;
}
B. P7863 「EVOI-RD1」飞鸟和蝉
每个点向周围地势比它低的点连边,问题就转为二分图匹配,推一下柿子可以发现体力消耗就是每条边两点权值差的和,也就是二分图最小权匹配,跑个mcmf即可。这题spfa跑的比较快,堆优化dijkstra要用pbds里的堆(stl的T了)。
#include <bits/extc++.h>
#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<ll, ll> pll;
const ll N = 5e3 + 2, M = 2e4 + 1, inf = 1e18;
ll n, m, a, b, tot, s, t;
ll cnt, he[N], d[N], h[N], x[51][51];
ll ne[M], to[M], c[M], w[M];
ll pe[N], pv[N], F, C;
inline void add(ll u, ll v, ll C, ll W) {
ne[cnt] = he[u], to[cnt] = v, c[cnt] = C, w[cnt] = W, he[u] = cnt++;
ne[cnt] = he[v], to[cnt] = u, c[cnt] = 0, w[cnt] = -W, he[v] = cnt++;
}
inline ll get_no(ll i, ll j) {
return (i - 1) * m + j;
}
inline bool dij(ll s, ll t) {
__gnu_pbds::priority_queue<pll, greater<pll>, pairing_heap_tag> q;
memset(d, 14, sizeof d), d[s] = 0;
q.push({0, s});
while (q.size()) {
pll T = q.top();
q.pop();
ll u = T.second;
if (d[u] < T.first)
continue;
for (ll i = he[u]; ~i; i = ne[i]) {
ll v = to[i], tw = d[u] + w[i] + h[u] - h[v];
if (c[i] && tw < d[v]) {
d[v] = tw, pv[v] = u, pe[v] = i;
q.push({d[v], v});
}
}
}
return d[t] < inf;
}
inline void mcmf(ll s, ll t) {
while (dij(s, t)) {
fu(i, 1, t) h[i] += d[i];
ll f = inf;
for (ll u = t; u ^ s; u = pv[u])
mn(f, c[pe[u]]);
F += f, C += h[t] * f;
for (ll u = t; u ^ s; u = pv[u]) {
c[pe[u]] -= f;
c[pe[u] ^ 1] += f;
}
}
}
int main() {
scanf("%lld%lld%lld%lld", &n, &m, &a, &b);
tot = n * m;
fu(i, 1, n) fu(j, 1, m) scanf("%lld", x[i][j]);
memset(he, -1, sizeof he);
ll dx[]{0, 0, 1, -1}, dy[]{1, -1, 0, 0}, o = 0;
s = 0, t = 2 * tot + 1;
fu(i, 1, n) fu(j, 1, m) {
++o;
add(0, o, 1, 0);
add(o + tot, t, 1, 0);
fu(k, 0, 3) {
ll nx = i + dx[k], ny = j + dy[k], no = get_no(nx, ny);
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m)
if (x[i][j] > x[nx][ny])
add(o, no + tot, 1, x[i][j] - x[nx][ny]);
}
}
mcmf(s, t);
printf("%lld %lld", tot - F, C);
}
C. P7835 「Wdoi-3」夜雀 dreaming
签到题,解同余方程或者利用周期性只需判断lcm和二倍lcm。
#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
#define f first
#define s second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
const ll N = 1e5 + 1, M = 1e9 + 7;
ll n, m;
ll a, b, c, d, l;
ll x[N], y[N], t[N], ans = 2e18;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b)
return x = 1, y = 0, a;
ll t = exgcd(b, a % b, y, x);
return y -= a / b * x, t;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m;
fu(i, 1, m) cin >> t[i] >> x[i] >> y[i];
fu(i, 1, m - 1) fu(j, i + 1, m) {
d = __gcd(t[i], t[j]);
l = t[i] * t[j] / d;
a = t[j] / d, b = t[i] / d;
a = a * y[i] - b * y[j];
c = x[j] - x[i] + y[i] - y[j];
ll x, y;
d = abs(exgcd(a, n, x, y));
if (c % d) {
mn(ans, l);
} else if (n / d > 1) {
a = n / d;
c = (x * c / d % a + a) % a;
mn(ans, (c ^ 1 ? 1 : 2) * l);
}
}
if (ans == 2e18)
cout << "Mystia will cook forever...";
else
cout << ans - 1;
}
D. T183638 晚宴(2021 CoE III E)
显然是个二分图最小权匹配,用堆优化dijkstra或者\(O(n ^ 3)\)的km算法,spfa应该卡不过。
#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
#define pii pair<ll, ll>
using namespace std;
typedef long long ll;
const ll N = 1.5e3, M = 5e5, inf = 1e18;
ll n, m, s, t;
ll cnt, he[N], d[N], h[N];
ll ne[M], to[M], c[M], w[M];
ll pe[N], pv[N], nx[N], vis[N], F, C;
inline void add(ll u, ll v, ll C, ll W) {
ne[cnt] = he[u], to[cnt] = v, c[cnt] = C, w[cnt] = W, he[u] = cnt++;
ne[cnt] = he[v], to[cnt] = u, c[cnt] = 0, w[cnt] = -W, he[v] = cnt++;
}
inline bool dij(ll s, ll t, ll m) {
priority_queue<pii, vector<pii>, greater<pii>> q;
memset(d, 14, sizeof d), d[s] = 0;
q.push({0, s});
while (q.size()) {
pii T = q.top();
q.pop();
ll u = T.second;
if (d[u] < T.first)
continue;
for (ll i = he[u]; ~i; i = ne[i]) {
ll v = to[i], tw = d[u] + w[i] + h[u] - h[v];
if (c[i] && tw < d[v]) {
d[v] = tw, pv[v] = u, pe[v] = i;
q.push({d[v], v});
}
}
}
return d[t] < inf;
}
inline void mcmf(ll s, ll t, ll m) {
while (dij(s, t, m)) {
fu(i, 1, m) h[i] += d[i];
ll f = inf;
for (ll u = t; u ^ s; u = pv[u])
mn(f, c[pe[u]]);
F += f, C += h[t] * f;
for (ll u = t; u ^ s; u = pv[u]) {
nx[pv[u]] = u - n;
c[pe[u]] -= f;
c[pe[u] ^ 1] += f;
}
}
}
int main() {
ll u, v, c, w;
memset(he, -1, sizeof he);
scanf("%lld%lld", &n, &m);
s = 0, t = 2 * n + 1;
fu(i, 1, n) {
add(0, i, 1, 0);
add(i + n, t, 1, 0);
}
fu(i, 1, m) {
scanf("%lld%lld%lld", &u, &v, &w);
add(u, v + n, 1, w);
}
mcmf(s, t, 2 * n + 1);
if (F ^ n)
puts("Impossible!");
else {
printf("%lld\n", C);
fu(i, 1, n) {
if (!vis[i]) {
for (ll j = i; !vis[j]; vis[j] = 1, j = nx[j])
printf("%lld ", j);
puts("");
}
}
}
return 0;
}
E. P3769 [CH弱省胡策R2]TATT
四维偏序,我写的是cdq套cdq,不会kd-tree。
#include <bits/extc++.h>
#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
#define g(a, b) get<b>(a)
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef tuple<ll, ll, ll, ll, ll, ll, ll> tp; //a, b, c, d, ans, cnt, f
const ll N = 1e5 + 10, M = 998244353;
ll t, n, m, k, ans;
ll a, b, c, d, e, f;
ll x[N], y[N], T[N], tot;
tp p[N], p1[N];
auto cmp2 = [](tp &a, tp &b) { return g(a, 1) ^ g(b, 1) ? g(a, 1) < g(b, 1) : a < b; };
auto cmp3 = [](tp &a, tp &b) { return g(a, 2) < g(b, 2); };
inline void upd(ll p, ll x) {
for (; p <= tot; p += p & -p)
mx(T[p], x);
}
inline void clr(ll p) {
for (; p <= tot; p += p & -p)
T[p] = 0;
}
inline ll ask(ll p) {
ll r = 0;
for (; p; p -= p & -p)
mx(r, T[p]);
return r;
}
void cal1(ll l, ll r) {
if (l == r)
return;
ll m = l + r >> 1, j = l;
cal1(l, m);
sort(p + l, p + m + 1, cmp3);
sort(p + m + 1, p + r + 1, cmp3);
fu(i, m + 1, r) {
auto &[a, b, c, d, ans, cnt, f] = p[i];
for (; g(p[j], 2) <= c && j <= m; ++j)
if (!g(p[j], 6))
upd(g(p[j], 3), g(p[j], 4));
if (f)
mx(ans, ask(d) + cnt);
}
fd(i, j - 1, l) if (!g(p[i], 6)) clr(g(p[i], 3));
sort(p + l, p + r + 1, cmp2);
cal1(m + 1, r);
}
void cal(ll l, ll r) {
if (l == r)
return;
ll m = l + r >> 1;
cal(l, m);
fu(i, l, r) g(p[i], 6) = i > m;
sort(p + l, p + r + 1, cmp2);
cal1(l, r);
sort(p + l, p + r + 1);
cal(m + 1, r);
}
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
fu(i, 1, n) {
cin >> a >> b >> c >> x[i];
p[i] = {a, b, c, x[i], 0, 0, 0};
}
//对第四维离散化
sort(x + 1, x + n + 1);
tot = unique(x + 1, x + n + 1) - x - 1;
gp_hash_table<ll, ll> ht;
fu(i, 1, tot) ht[x[i]] = i;
fu(i, 1, n) g(p[i], 3) = ht[g(p[i], 3)];
//按第一维排序,去重
sort(p + 1, p + n + 1);
t = 1;
fu(i, 2, n + 1) if (p[i] != p[t]) {
p[++m] = p[t];
g(p[m], 4) = g(p[m], 5) = i - t;
t = i;
}
cal(1, m);
fu(i, 1, m) mx(ans, g(p[i], 4));
cout << ans;
}
F. P3369 【模板】普通平衡树
方法很多,这里直接用pbds里的rb_tree
#include <bits/extc++.h>
#include <bits/stdc++.h>
#define fu(a, b, c) for (ll a = b; a <= c; a++)
#define fd(a, b, c) for (ll a = b; a >= c; a--)
#define mx(a, b) a = max(a, b)
#define mn(a, b) a = min(a, b)
using namespace __gnu_pbds;
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
const ll N = 1e5 + 10, M = 998244353;
ll t, n, m, k, ans;
ll a, b, c, d, e, f;
ll x[N], y[N], z[N];
pll p[N];
int main() {
ios::sync_with_stdio(0), cin.tie(0);
tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> T;
cin >> t;
fu(i, 1, t) {
cin >> a >> b;
switch (a) {
case 1:
T.insert((b << 17) + i);
break;
case 2:
T.erase(T.lower_bound(b << 17));
break;
case 3:
cout << T.order_of_key(b << 17) + 1 << '\n';
break;
case 4:
cout << (*T.find_by_order(b - 1) >> 17) << '\n';
break;
case 5:
cout << (*--T.lower_bound(b << 17) >> 17) << '\n';
break;
case 6:
cout << (*T.lower_bound(b + 1 << 17) >> 17) << '\n';
break;
}
}
}