CSP2022 游记
我还是写一下吧……
Day -1
模拟赛。
成为机房垫底人。
Day 0
上午
补昨天模拟赛 T4。
下午
补昨天模拟赛 T4。
晚上
补昨天模拟赛 T4。
补完了后把昨天胡了没写的 APIO2014 连珠线写了。挺有意思的反悔贪心树形 dp 技巧。
然后回家了。
Day 1
上午
因为只去提高组,所以在家里 VP 了 CSP-S2021 的 T1-3。
为了适应考场没有代码补全、语法高亮之类的东西,赶紧把插件关了写。(flag)
T1,T3 半小时写完,T2 花了大概 1h 就写掉了。
11:00 起身去文渊,好坐校车去考点。
遇到了好多同学。
下午
12:30 校车出发。
大约 13:30 的样子抵达杭师大。
在里面面到了 djwj233。
devin 没来。
14:00 左右进了机房。
那边的工作人员说话声好大啊。
14:25 解压密码发下来,给的是 Belief2022
,结果实际上是 belief2022
???
我想,这实在是无法可想了。
开题。
先看 T1T2.
T1 大概先 bfs 一轮找到每个点距离那些点不超过 \(k\)?然后枚举似乎可以 meet in the middle?
T2 似乎随便分类讨论一下 rmq 就完了。
14:30 能开写了,先敲一个码头。以 T2 为例。(原来考场 VS Code 是有代码补全和语法高亮哒?)
// with code highlight and code completion, I'd fly.
#include <algorithm>
#include <stdio.h>
#include <vector>
typedef unsigned uint;
typedef unsigned long long ullt;typedef long long llt;
typedef bool bol;typedef char chr;typedef void voi;
typedef double dbl;
template<typename T>bol _min(T&a,T b){return b<a?(a=b,true):false;}
template<typename T>bol _max(T&a,T b){return a<b?(a=b,true):false;}
int main(){
#ifdef MYEE
freopen("QAQ.in","r",stdin);
freopen("QAQ.out","w",stdout);
#else
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
#endif
return 0;
}
// belief2022
/*
g++ game.cpp -o game -std=c++14 -lm -DMYEE -Wall
*/
厘清细节后就开始写,T1 花了 30min 就码完了。
做为优秀的稳健型选手,我维护了前 \(5\) 优解!会不会被卡常啊。
一遍过不了样例,怎么回事?原来距离是不超过 \(k+1\) 啊。
两遍过不了样例,怎么回事?原来我没有判 \(B,C\) 连通性啊。
然后直接过了大样例,稍微注意了一下 ullt
有没有开全,然后就码 T2 去了。
厘了一下细节,T2 花了 30min 就码完了,一遍过大样例,感觉不会写挂也就没有拍了。
在 线 乳 人。
struct max_ST{ // pogSTd
std::vector<uint>Log2;
std::vector<std::vector<llt> >S;
voi build(llt*A,uint n){
Log2.resize(n+1),Log2[0]=-1;
for(uint i=1;i<=n;i++)Log2[i]=Log2[i>>1]+1;
S.clear(),S.resize(Log2[n]+1,std::vector<llt>(n));
for(uint i=0;i<n;i++)S[0][i]=A[i];
for(uint i=1;i<=Log2[n];i++)for(uint j=0;j+(1u<<i)<=n;j++)
S[i][j]=std::max(S[i-1][j],S[i-1][j+(1u<<(i-1))]);
}
llt find(uint l,uint r){uint s=Log2[r-l];return std::max(S[s][l],S[s][r-(1u<<s)]);}
};
struct min_ST{ // pogSTd
std::vector<uint>Log2;
std::vector<std::vector<llt> >S;
voi build(llt*A,uint n){
Log2.resize(n+1),Log2[0]=-1;
for(uint i=1;i<=n;i++)Log2[i]=Log2[i>>1]+1;
S.clear(),S.resize(Log2[n]+1,std::vector<llt>(n));
for(uint i=0;i<n;i++)S[0][i]=A[i];
for(uint i=1;i<=Log2[n];i++)for(uint j=0;j+(1u<<i)<=n;j++)
S[i][j]=std::min(S[i-1][j],S[i-1][j+(1u<<(i-1))]);
}
llt find(uint l,uint r){uint s=Log2[r-l];return std::min(S[s][l],S[s][r-(1u<<s)]);}
};
看 T3,动 态 基 环 内 向 树。
什么鬼啊。
看 T4。摆了。这么大码量有意思哦?
\(k=1\) 裸树上差分,\(k=2\) 直接全在链上选点 ddp,\(k=3\) 稍微讨论一下链外点的 ddp,随便讨论一下写个树上倍增就完了?
// feeling bad that being not able to type in Chinese.
// link-cut ji huan nei xiang shu ?
// do T4 first, plz.
// maybe easier than T3.
仔细想了想还是不要莽。
发现似乎直接让基环内向树森林的每个点出度均为 \(1\) 即可。
那不是直接写个 hash 就好了。
把出边相同的点整一起,搞一个线段树维护一下,区间 clear
区间 fill
全局求和。
// as they're all easy to do.
// while, let me think...
// the out deg of the whole points should all be 1.
// we can take the points whose out points same together, and do it with a Segment Tree, which is filled with hash.
// then it may be ok?
// by randomly making a map f: [1,n] -> [0,2^64), and sum the hash val, the possiblity of successiful check can be accepted.
// as the attack of birthday tell as that it's always ok, for n much smaller than 2^32.
// -- yours, Myee Ye.
跑得很快啊!
此时 16:39,也就是 T3 花了 1h 就写完了。
考虑 T4 的细节。
// oh, i've had T3 done.
// now it's 16:39.
// can I finish it in 2 hours?
// just go for it!
// when watching back the whole contest, to think of it:
// is it a contest of Data Structure and Graph Theory?
然后 17:20 写完了 \(k=1,2\)。
\(k=2\) 写了个 \(2\times2\) 的转移矩阵。直接 min-plus 矩阵乘法维护了。
// now it's 17:20, when I can pass the example 3 whose k=2.
\(k=3\) 写了个 \(5\times5\) 的转移矩阵。
对应向量 \(\begin{pmatrix}f_1\\f_2\\f_3\\f_4\\f_5\end{pmatrix}\),其中 \(f_1\) 表示到当前根的最小权;\(f_2,f_3\) 表示到 \(1\) 的两个儿子的最小权,其中 \(2\) 在链上;\(f_4,f_5\)表示到 \(2\) 的两个儿子的最小权,其中 \(4\) 在链上。
合并左右两半时稍微讨论一下就好了。
会不会被卡常啊?
然后 18:02 码完了。
// now it's 18:02, when I can pass the example 4 whose k=3.
仔细检查一下,有没有什么问题?
光转移矩阵的部分几乎就爆空间啦!(限制 \(1{\rm GB}\))
卡一卡矩阵大小。
卡成 \(4\times4\) 吧。\(4,5\) 可以合并。
稳健的。
此时是 18:19。
// well, it get MLE.
// solve it at 18:19.
晚上
回到家了。
发现 T3 可以不用线段树维护,可以直接压边集栈维护。
发现 T4 可以进一步压成 \(3\times3\) 的矩阵。
发现 T4 可以点分,不用维护矩阵。
Luogu 上 T1,T2,T4 开放民间数据评测,直接过了,感觉很稳。
infoj 上过了 T3,T4,T1T2 没测。
造 CSP-J2022 信友队数据评测 T4 的数据。
发现数据范围很小,\(n\le500,k\le100,v\le10^9\),感觉很憨。
随便写了个暴力,测了一下样例。
然后开始拿我的数据生成工具摁造数据。生成工具大概就长这样:
system("g++ gen.cpp -o gen -Wall -std=c++11");
FILE*fin=fopen("data_task.txt","r");
int l,r;
while(fscanf(fin,"%d%d",&l,&r)==2)
{
fgets(C,100000,fin);
// fprintf(stderr,"%s\n",C),fflush(stderr);
char*c=C;
while(*c&&*c!='\r'&&*c!='\n')c++;
*c='\0';
sprintf(D,"gen %s",C);
while(l<=r)
{
sprintf(Sys,D,l);
fprintf(stderr,"%s\n",Sys),fflush(stderr);
system(Sys);
l++;
}
}
fclose(fin);
Generater 不敢乱发。好像写了一个长方形范围里的的随机点集生成器,然后删除重点。为了创人,我的 data_task.txt
写的很***钻。
Day 2
XJOI 上测了四题,全部过了。
Luogu T3 民间数据开放后测了也过了。
期望得分:\(100+100+100+100\)。
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/CSP2022.html