CSP-S 2022 云游 reverse 记
模拟赛挂了。
啊HB的J组取消了,S组高中生正在争取!
模拟赛挂了。
啊HB的J组取消了,S组高中生正在争取!HB的S组争取到了!
模拟赛挂了。
啊HB的J组取消了,S组高中生正在争取!HB的S组争取到了!又取消了!
焯,看来今年只能云游CSP-S了啊/ll
10.29的晚上报名了洛谷的自测,看到了4道题的名字(果然奇奇怪怪),瞥了一眼题面发现怎么都这么长啊!压力一下就上来了啊!
赶紧睡觉了。
\(1\)
早上教练组织模拟CSP,\(8\) 点准时开题。
看到了T1。想了 \(20\min\) 没思路,于是转战T2。
\(T2\) 一眼看过去很像个博弈论,读完思考了 \(30s\) 发现是憨憨题,这不就分亿下类就做完了吗。然后写写写,开 \(6\) 个 ST 表维护区间最大最小最大非正最小非负然后大力分类讨论,居然一点都不难调,写完大概已经过了 \(60\min\)。
有点慌啊,\(T1\) 还没动呢!转战 \(T1\),思考了亿下发现可以枚举中间的 \(\rm BC\) 两点然后剩下的两个点预处理。那不就简单了!直接糊个 spfa,然后预处理一下前三大的值剩下直接瞎搞。意料之中地很好写,写完就丢去看 \(T3\) 了。
这时候过了 \(100\min\)。看 \(T3\),花了快 \(10\min\) 阅读理解后推了一下性质发现就是判断是不是基环树森林,然后充要条件是每个点的出度是 \(1\)。那第二个条件好像包含了第一个啊...?十分疑惑,一度怀疑读错了题。暴力至少有 \(50\) 了,那正解呢,就是判断每个点的出度是不是都为 \(1\)。开桶应该不行,隐隐之中感觉像是什么玄学哈希之类的东西,但我不会啊!想了亿会怎么哈希乱搞,没啥头绪,于是索性先看看 \(T4\)。
题面不长,然后以为前 \(44\) 分就是序列 \(dp\),飞快码完后测第二个样例发现他居然可能走出去!那 \(k=3\) 就假了啊!tnnd不写了,没意义了/kk。
继续盯 \(T3\) 无果后,决定先把暴力打了。还要判断每条边是不是连的,用了unordered_map
。\(10\min\)写完发现正确性没问题,然而只有操作1和3的大样例跑了 \(8s\)?然而马上发现瓶颈在 scanf
,写了个快读就 \(2s\) 了。继续卡一卡,尝试用map
换了unordered_map
,发现就莫名其妙的 \(1s\) 了。unordered_map
怎么这么逊啊。
现在估分 \(100+100+50+24=274\),其中T3可能不止 \(50\)。剩下还有不到1h,摸了会鱼,然后盯T3盯到结束仍然无果/kk
结束了。
看到洛谷上有自测,遂将代码提交。我去!\(T1\) 挂成 \(10\) 了?
慌了啊慌了啊!马上开始 debug!检查了最短路,预处理以及枚举部分均未发现锅。忽然看到读入的点权是 \(1e18\),诶我不是开了LL吗,然后:
for(int i = 2; i <= n; ++i) scanf("%d", val + i);
《拿 \(\tt \%d\) 硬抗\(10^{18}\)》
寄!
洛谷 \(T3\) 还没有数据,在帖子里发现了一个叫 \(\rm infOJ\) 的东西,遂到上面交了一发 \(T3\),有 \(60\)。
就这样了吧。哎,本来就平平无奇的大众分然后就莫名其妙 \(-90\) 了,我不做人辣!!!
下午在 \(\rm infOJ\) 上翻别人 \(T3\) AC的记录,成功看懂了一种哈希方式。
给每个点赋随机权 \(h_u\),然后实时记录当前所有出度为奇数的点的 \(h_u\) 的 \(\text{xor}\) 和,并且记录是不是 \(n\) 条边。这样就可以 \(\mathcal O(1)\) 判断是不是YES了。挺妙的。好像叫 Sum Hash / Xor Hash
上次见到类似的是 Ynoi 的大母神。所以说什么判断相等或者什么一些复杂特殊情况且无法直接维护的可以考虑这样搞哈希。
\(T4\) 好像是类似 ddp 的矩阵乘法维护 dp 套树剖。当时应该多骗一点分的,\(k=3\) 的序列 \(dp\) 后来发现真不难想,还有 \(k=1\) 不送吗,为啥不写捏?小编也不知道。
还有这个 \(T3\) 的暴力,有人暴力拿了 \(40\),有人能拿 \(60\),还有人能拿 \(70\)。所以就算写暴力也得考虑优秀的实现方式,因为能骗一点是一点。
所以能拿的分一分都不要丢!
upd:\(\tt reverse\) 了,\(T1\) 在西西艾氟的脚造数据下拿 \(\tt \%d\) 读 \(10^{18}\) 跑满了,\(+90 pts\)。
\(T3\) 的暴力加上不可以总司令能拿 \(80\)!可惜了/kk
\(100 + 100 + 60 + 24 = 284\),仍然平平无奇的大众分。
考场代码
$T1$ $100$
#include <bits/stdc++.h>
#define File(X) freopen(#X ".in", "r", stdin), freopen(#X ".out", "w", stdout)
#define FILE(X, Y) freopen(#X, "r", stdin), freopen(#Y, "w", stdout)
#define Debug 1
#define emp emplace_back
using namespace std;
using LL = long long;
mt19937 gen(chrono::system_clock::now().time_since_epoch().count());
class DEBUG {
int _debug = 1, _IO = 0;
public: DEBUG(int x = 1) { _debug = x; }
inline void IOS() { if(!_IO) cin.tie(0)->sync_with_stdio(0), cout.tie(0)->sync_with_stdio(0); }
inline void shift(int x) { _debug = x; }
inline void write() {}
template <typename T, typename ...A> inline void write(T x, A ...k) { if(_debug) cout << x, write(k...); }
template <typename T> inline void writeln(T x) { cout << x << endl; }
template <typename T, typename ...A> inline void writeln(T x, A ...k) { if(_debug) cout << x << ' ', writeln(k...); }
template <typename T> inline void debug(const T *arr, int l, int r) {
if(_debug) { for(int i = l; i <= r; ++i) cout << arr[i] << ' '; cout << endl; }
}
}D;
const int N = 2505;
int n, m, k;
LL val[N];
vector <int> Link[N];
int d[N][N];
struct Node {
LL v = 0; int pos = 0;
inline bool operator < (Node A) const {
return v < A.v;
}
}num[N][3];
namespace Spfa {
bitset <N> vis;
int dis[N];
inline void work(int st) {
memset(dis, 0x3f, sizeof dis), dis[st] = 0;
vis.reset(), vis[st] = 1;
deque <int> Q; Q.push_front(st);
while(Q.size()) {
int u = Q.front(); Q.pop_front();
vis[u] = 0;
for(auto v : Link[u]) {
if(dis[v] > dis[u] + 1) {
dis[v] = dis[u] + 1;
if(!vis[v]) {
vis[v] = 1;
if(Q.size() && dis[v] < dis[Q.front()]) Q.push_front(v);
else Q.push_back(v);
}
}
}
}
for(int i = 1; i <= n; ++i) d[st][i] = dis[i];
}
}
signed main() {
FILE(in.txt, Ans.txt);
// File(holiday);
scanf("%d %d %d", &n, &m, &k); ++k;
for(int i = 2; i <= n; ++i) scanf("%lld", val + i); // 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
for(int i = 1, x, y; i <= m; ++i) {
scanf("%d %d", &x, &y);
Link[x].emp(y), Link[y].emp(x);
}
for(int i = 1; i <= n; ++i) Spfa::work(i);
// for(int i=1;i<=n;++i)D.debug(d[i], 1, n);
for(int i = 2; i <= n; ++i) {
for(int j = 2; j <= n; ++j) {
if(i == j) continue;
if(d[1][j] > k || d[j][i] > k) continue;
if(val[j] >= num[i][0].v) num[i][2] = num[i][1], num[i][1] = num[i][0], num[i][0] = {val[j], j};
else if(val[j] >= num[i][1].v) num[i][2] = num[i][1], num[i][1] = {val[j], j};
else if(val[j] >= num[i][2].v) num[i][2] = {val[j], j};
}
}
// for(int i = 1; i <= n; ++i, cout << endl) for(int j = 0; j < 3; ++j) cout << num[i][j].pos << ' ';
LL ans = 0;
for(int i = 2; i <= n; ++i) {
for(int j = 2; j <= n; ++j) {
if(i == j) continue;
if(d[i][j] > k) continue;
if(!num[i][0].v) continue;
if(!num[j][0].v) continue;
for(int x = 0; x < 3; ++x)
for(int y = 0; y < 3; ++y) {
if(!num[i][x].v || !num[j][y].v) continue;
if(num[i][x].pos == num[j][y].pos) continue;
if(num[i][x].pos == i) continue;
if(num[i][x].pos == j) continue;
if(num[j][y].pos == i) continue;
if(num[j][y].pos == j) continue;
ans = max(ans, val[i] + val[j] + num[i][x].v + num[j][y].v);
}
}
}
cout << ans;
return 0;
}
/*
ALL MY LIFE I'VE BEEN CHASING DOWN A DREAM
BUT ALL THE MOMENTS IN BETWEEN THAT IS ALL I NEED
*/
$T2$ $100$
#include <bits/stdc++.h>
#define File(X) freopen(#X ".in", "r", stdin), freopen(#X ".out", "w", stdout)
#define FILE(X, Y) freopen(#X, "r", stdin), freopen(#Y, "w", stdout)
#define Debug 1
#define emp emplace_back
using namespace std;
using LL = long long;
mt19937 gen(chrono::system_clock::now().time_since_epoch().count());
class DEBUG {
int _debug = 1, _IO = 0;
public: DEBUG(int x = 1) { _debug = x; }
inline void IOS() { if(!_IO) cin.tie(0)->sync_with_stdio(0), cout.tie(0)->sync_with_stdio(0); }
inline void shift(int x) { _debug = x; }
inline void write() {}
template <typename T, typename ...A> inline void write(T x, A ...k) { if(_debug) cout << x, write(k...); }
template <typename T> inline void writeln(T x) { cout << x << endl; }
template <typename T, typename ...A> inline void writeln(T x, A ...k) { if(_debug) cout << x << ' ', writeln(k...); }
template <typename T> inline void debug(const T *arr, int l, int r) {
if(_debug) { for(int i = l; i <= r; ++i) cout << arr[i] << ' '; cout << endl; }
}
}D;
const int N = 1e5 + 5, inf = 0x3f3f3f3f;
int n, m, a[N], b[N], q;
struct ST {
int f[N][20], g[N][20];
inline void build(int *arr, int M) {
for(int i = 1; i <= M; ++i) f[i][0] = g[i][0] = arr[i];
for(int j = 1; j < 20; ++j)
for(int i = 1; i + (1 << j) - 1 <= M; ++i) {
f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
g[i][j] = min(g[i][j - 1], g[i + (1 << j - 1)][j - 1]);
}
}
inline int qmax(int l, int r) {
int k = __lg(r - l + 1);
return max(f[l][k], f[r - (1 << k) + 1][k]);
}
inline int qmin(int l, int r) {
int k = __lg(r - l + 1);
return min(g[l][k], g[r - (1 << k) + 1][k]);
}
}A, B, A1, A2, B1, B2;
vector <int> pos1, pos2; // position of 0(A, B)
int a1[N], a2[N], b1[N], b2[N];
inline void judge(LL &ans, int flg1, int flg2) {
if(flg1) ans = max(ans, 0LL);
if(flg2) ans = min(ans, 0LL);
}
signed main() {
// freopen("in.txt", "r", stdin), freopen("Ans.txt", "w", stdout);
File(game);
scanf("%d %d %d", &n, &m, &q);
for(int i = 1; i <= n; ++i) scanf("%d", a + i);
for(int i = 1; i <= m; ++i) scanf("%d", b + i);
for(int i = 1; i <= n; ++i) if(!a[i]) pos1.emp(i);
for(int i = 1; i <= m; ++i) if(!b[i]) pos2.emp(i);
for(int i = 1; i <= n; ++i) a1[i] = a[i] > 0 ? a[i] : inf;
for(int i = 1; i <= n; ++i) a2[i] = a[i] < 0 ? a[i] : -inf;
for(int i = 1; i <= m; ++i) b1[i] = b[i] > 0 ? b[i] : inf;
for(int i = 1; i <= m; ++i) b2[i] = b[i] < 0 ? b[i] : -inf;
A.build(a, n), B.build(b, m);
A1.build(a1, n), A2.build(a2, n);
B1.build(b1, m), B2.build(b2, m);
for(int l1, r1, l2, r2; q--; ) {
scanf("%d %d %d %d", &l1, &r1, &l2, &r2);
LL mx1 = A.qmax(l1, r1), mn1 = A.qmin(l1, r1);
LL mx2 = B.qmax(l2, r2), mn2 = B.qmin(l2, r2);
auto pa = lower_bound(pos1.begin(), pos1.end(), l1);
int flg1 = (pa == pos1.end() ? inf : *pa) <= r1;
auto pb = lower_bound(pos2.begin(), pos2.end(), l2);
int flg2 = (pb == pos2.end() ? inf : *pb) <= r2;
LL ans = 0;
if(mx1 > 0 && mn1 < 0) {
if(mx2 > 0 && mn2 < 0) ans = max(A1.qmin(l1, r1) * mn2, A2.qmax(l1, r1) * mx2);
else if(mx2 <= 0) ans = mn1 * B2.qmax(l2, r2);
else if(mn2 >= 0) ans = mx1 * B1.qmin(l2, r2);
}
else if(mn1 >= 0) {
if(mx2 > 0 && mn2 < 0) ans = A1.qmin(l1, r1) * mn2;
else if(mx2 <= 0) ans = A1.qmin(l1, r1) * mn2;
else if(mn2 >= 0) ans = mx1 * mn2;
}
else if(mx1 <= 0) {
if(mx2 > 0 && mn2 < 0) ans = A2.qmax(l1, r1) * mx2;
else if(mx2 <= 0) ans = mn1 * mx2;
else if(mn2 >= 0) ans = A2.qmax(l1, r1) * mx2;
}
judge(ans, flg1, flg2);
printf("%lld\n", ans);
}
return 0;
}
/*
ALL MY LIFE I'VE BEEN CHASING DOWN A DREAM
BUT ALL THE MOMENTS IN BETWEEN THAT IS ALL I NEED
*/
$T3$ $60$
#include <bits/stdc++.h>
#define File(X) freopen(#X ".in", "r", stdin), freopen(#X ".out", "w", stdout)
#define FILE(X, Y) freopen(#X, "r", stdin), freopen(#Y, "w", stdout)
#define Debug 1
#define emp emplace_back
using namespace std;
using LL = long long;
mt19937 gen(chrono::system_clock::now().time_since_epoch().count());
class DEBUG {
int _debug = 1, _IO = 0;
public: DEBUG(int x = 1) { _debug = x; }
inline void IOS() { if(!_IO) cin.tie(0)->sync_with_stdio(0), cout.tie(0)->sync_with_stdio(0); }
inline void shift(int x) { _debug = x; }
inline void write() {}
template <typename T, typename ...A> inline void write(T x, A ...k) { if(_debug) cout << x, write(k...); }
template <typename T> inline void writeln(T x) { cout << x << endl; }
template <typename T, typename ...A> inline void writeln(T x, A ...k) { if(_debug) cout << x << ' ', writeln(k...); }
template <typename T> inline void debug(const T *arr, int l, int r) {
if(_debug) { for(int i = l; i <= r; ++i) cout << arr[i] << ' '; cout << endl; }
}
};
inline int read() {
int x = 0, w = 0, ch = getchar();
for(; !isdigit(ch); ch = getchar()) w |= ch == 45;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return w ? -x : x;
}
const int N = 5e5 + 5;
int n, m, q;
vector <int> Link[N];
int bucket[N], deg[N];
inline LL id(int x, int y) {
return x * 1000000LL + y;
}
map <LL, int> mp;
signed main() {
// FILE(in.txt, Ans.txt);
File(galaxy);
n = read(), m = read();
for(int i = 1, x, y; i <= m; ++i) {
x = read(), y = read();
Link[y].emp(x), ++deg[x];
}
for(int i = 1; i <= n; ++i) ++bucket[deg[i]];
q = read();
for(int op, x, y, i = 1; i <= q; ++i) {
op = read();
if(op == 1) {
x = read(), y = read();
--bucket[deg[x]--], ++bucket[deg[x]];
mp[id(x, y)] = 1;
puts(bucket[1] == n ? "YES" : "NO");
}
if(op == 2) {
x = read();
for(auto v : Link[x])
if(!mp[id(v, x)]) --bucket[deg[v]--], ++bucket[deg[v]], mp[id(v, x)] = 1;
puts(bucket[1] == n ? "YES" : "NO");
}
if(op == 3) {
x = read(), y = read();
--bucket[deg[x]++], ++bucket[deg[x]];
mp[id(x, y)] = 0;
// mp.erase(id(x, y));
puts(bucket[1] == n ? "YES" : "NO");
}
if(op == 4) {
x = read();
for(auto v : Link[x])
if(mp[id(v, x)]) --bucket[deg[v]++], ++bucket[deg[v]], mp[id(v, x)] = 0;
puts(bucket[1] == n ? "YES" : "NO");
}
#if 0
if(clock() * 1.0 / CLOCKS_PER_SEC <= 1.8) {
for(int j = i + 1; j <= q; ++j) puts("NO");
return 0;
}
#endif
}
// cout << clock();
return 0;
}
/*
ALL MY LIFE I'VE BEEN CHASING DOWN A DREAM
BUT ALL THE MOMENTS IN BETWEEN THAT IS ALL I NEED
*/
$T4$ $24$
#include <bits/stdc++.h>
#define File(X) freopen(#X ".in", "r", stdin), freopen(#X ".out", "w", stdout)
#define FILE(X, Y) freopen(#X, "r", stdin), freopen(#Y, "w", stdout)
#define Debug 1
#define emp emplace_back
using namespace std;
using LL = long long;
mt19937 gen(chrono::system_clock::now().time_since_epoch().count());
class DEBUG {
int _debug = 1, _IO = 0;
public: DEBUG(int x = 1) { _debug = x; }
inline void IOS() { if(!_IO) cin.tie(0)->sync_with_stdio(0), cout.tie(0)->sync_with_stdio(0); }
inline void shift(int x) { _debug = x; }
inline void write() {}
template <typename T, typename ...A> inline void write(T x, A ...k) { if(_debug) cout << x, write(k...); }
template <typename T> inline void writeln(T x) { cout << x << endl; }
template <typename T, typename ...A> inline void writeln(T x, A ...k) { if(_debug) cout << x << ' ', writeln(k...); }
template <typename T> inline void debug(const T *arr, int l, int r) {
if(_debug) { for(int i = l; i <= r; ++i) cout << arr[i] << ' '; cout << endl; }
}
}D;
const int N = 3005;
int n, k, q;
vector <int> Link[N];
int id[N];
LL f[N];
LL val[N];
int dep[N], fa[N], son[N], sz[N], top[N];
namespace Div {
void dfs1(int u, int fx) {
fa[u] = fx, dep[u] = dep[fx] + 1, sz[u] = 1;
for(auto v : Link[u]) if(v != fx) {
dfs1(v, u), sz[u] += sz[v];
if(sz[son[u]] < sz[v]) son[u] = v;
}
}
void dfs2(int u, int tp) {
top[u] = tp;
if(son[u]) dfs2(son[u], tp); else return;
for(auto v : Link[u]) if(v != fa[u] && v != son[u]) dfs2(v, v);
}
inline int Lca(int x, int y) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
}
}
inline int split(int A, int B) { // x -> y
int x = A, y = B;
int t = Div::Lca(x, y), len = dep[x] + dep[y] - 2 * dep[t] + 1;
for(int i = 1; i <= dep[A] - dep[t]; ++i) {
id[i] = x, x = fa[x];
}
id[dep[A] - dep[t] + 1] = t;
for(int i = len; i > len - (dep[B] - dep[t]); --i) {
id[i] = y, y = fa[y];
}
// D.debug(id, 1, len);
return len;
}
inline LL dp(int M) {
for(int i = 1; i <= M; ++i) f[i] = 1e17;
f[1] = val[id[1]];
for(int i = 2; i <= M; ++i) {
for(int j = 1; j <= k; ++j)
if(i - j >= 1) f[i] = min(f[i], f[i - j]);
f[i] += val[id[i]];
}
// D.debug(f, 1, M);
return f[M];
}
signed main() {
FILE(in.txt, Ans.txt);
// File(transmit);
scanf("%d %d %d", &n, &q, &k);
for(int i = 1; i <= n; ++i) scanf("%lld", val + i);
for(int i = 1, x, y; i < n; ++i) {
scanf("%d %d", &x, &y);
Link[x].emp(y), Link[y].emp(x);
}
Div::dfs1(1, 0), Div::dfs2(1, 1);
for(int x, y; q--; ) {
scanf("%d %d", &x, &y);
printf("%lld\n", dp(split(x, y)));
}
return 0;
}
/*
ALL MY LIFE I'VE BEEN CHASING DOWN A DREAM
BUT ALL THE MOMENTS IN BETWEEN THAT IS ALL I NEED
*/