NOIP 2023 游记
NOIP 2023 游记
N日功力,结汇与此。
题目过于可怕,感觉该次比赛分数线可能比 CSPS 高。
DAY -5 2023/11/12
听同班同学 LZL 描述 NOIP (可能会出黑题、去年的喵了个喵),感觉异常可怕。虽然我以 CSPS 150 分的高分挤进初中前十,但 NOIP 能不能过,还是个巨大的问号。为此,我于该天在洛谷写了一堆(看上去没什么卵意义的)题目,水了几乎一天的谷,并未好好复习下周本应准备的 whk 。
DAY -3~-2 2023/11/14-15
这两天 whk 期中考试,听LZL说LRZ巨佬已于几天前翘课请假,备战 NOIP ,感到非常不可思议。
DAY -1 2023/11/16
whk 被我考寄了,估计连年前三十都没有。 回来加紧复习 NOIP ,却感觉自己脑海里一片空白,该会考的线段树、最小生成树、KMP(这些还好都不于这次出现)要学的一个没有学。
尝试祈求 ZYH(她居然会玩 Python )的庇护,试着加她 QQ(其实也没什么事,就是很好奇),却很明显失败。唉,RP大减、大减。
熬到午夜十二点,睡了。
DAY 0 2023/11/17
翘课。大早上起来打了一会 MC,然后被家长带着去高铁站汇合(总算认住了SYN , ZXR , LJH等神犇)。上午坐车做了 4 个小时,在车上写了两道题,浅浅的读了徐西岭《整型溢出》,然后就是摆。
高铁 1:40 到达,在等公交时,还看见一大批外校学生。他们看上去队伍庞大,加上我们学校的教练和他们教练看上去关系不错,给我一种莫名的恐惧。
我们到上饶,吃了一顿盖浇饭后,被安排住到 NOI 官网上江西省推荐的住宿地点(什么饶派数字文创酒店),价格较高,环境也好。我和巨佬 LRZ 分在同一间。尝试提交了车上离线写的两道题,但是只 A 过了一题,剩下一题莫名其妙的挂了(我太蒟了)。然后开始疯狂写题,大概写了很久吧,不过仅仅写了一些简单的地痞、广搜。
晚上 7:30 吃完外卖后,就开摆了,先是玩了会东方,但居然被琪露诺搞得生不如死,再是开了个新档玩 MC ,顺便在后台下载一些和信息学有关的东西。这时LZR却说要去其他房间什么“面基”,大概 10 分钟后回来。结果“一去不复返”,我没了他的热点,进入了断网模式。
LRZ 回来后,终于才发现了酒店密码是八个八(可能是从别的房间的人里学来的),这就逆天好吧。
DAY 0.5 2023/11/17 11:00-2023/11/18 凌晨
打模板!
我想赶紧学一下线段树,怕会考,如果考到了的话就药剂,可LRZ提醒我,现在学的话考场上也背不出来,说完他就去敲图论中的最短路、缩点、割点等一系列图论模板了。可怜的我,只能再敲一遍 spfa 、并查集、线性筛等模板,这期间他还给我看了一下 cf 上的一场比赛,可惜打不了。
时间来到凌晨,我打卡看到是中吉。然后以一道红题矩阵加法开启今天的第一道题,没想到,第一遍就A过了。
LRZ 定了两个闹钟,一个是 6:00 的,一个是 6:30 的,计划是先以 6:00 做预备,然后 6:30 再做正式的起床,然后去写 A+B Problem. 就这样定了。在 0:30 的时候,我们睡了。
Day 1 2023/11/18
我醒来时,我们学校的教练在敲门, LRZ 过去开,教练进来后告诉我们已经 6:50 了,要于 7:15 进入酒店餐厅吃早餐。我大惊,看来两闹钟没起效,匆忙起床收东西,现在没时间写 A+B Problem 来增强信心了。
餐厅里汇集了从四面八方来的学生和陪同他们的教练。他们各自汇拢在一起,有一批还在讨论什么可持久化并查集,这使我感到竞争非常非常的激烈。早餐后,叫了个滴去考场,在门外等着。
我在考场外收拾自己的东西,听见他们都在祈祷什么总司令、CCF 的脚,螈题什么的,太强了。我也是这样期盼的。
过检查进考场后,换了个“暴力出奇迹”的 NOI LINUX 自带壁纸(右击桌面,点那个什么 background 即可选择其他壁纸),玩了几把贪吃蛇(在 code::block 中的菜单里有个什么 game,专供蒟蒻食用),用 geany 敲了一下快读和快速幂(看到有人在敲 namespace FastIO,恐怖如斯)。
但是在 8:30 开考时,点击网页那个下载链接,所有机子都 404 ,没有人能够正常下载比赛题目,在我的视野内,所有人都恐慌至极。这里是 NOIP,不是 CSPJ,时间的紧迫早已在其他选手的游记中暴露无遗。在 8:35 时,监考老师汇报了真实情况(机子出了亿点点问题),并提示我们重启电脑,并在磁盘上不会保留先前写入的任何内容。这下,有一些人没什么反应,反正一定会有加时,而有些人——可能是敲 namespace FastIO 的大佬则感觉到了不公,直接“啊”起来。8:40 时,电脑重启完成,同时桌面上多了一个 zip 格式的压缩包——即今年题目。所有选手获得了 15 分钟的加时,考试结束时间延长为 13:15。没人为多出来的 5 分钟而感到欣喜,也没人为失去的 namespace FastIO 而感到惋惜,大家一致进入了敲代码的模式,可本蒟蒻却从头开始,花了 15 分钟读了一遍 pdf ,现在看来就是浪费时间。
T1 词典
看完 pdf 后,发现有人 T1 代码已经写满了屏幕,有的人已经在写 T2,有人在看 T3,意识到自己必须赶紧开 T1。于是写了个含 sort 的代码,甚至不知算法是否正确,就过了大样例。
#include<bits/stdc++.h>
#define I using
#define AK namespace
#define NOIP std
I AK NOIP;
inline int rd(){
int x=0,f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=((x<<3)+(x<<1)+(ch^48));
return x*f;
}const int maxn=3005;
struct str{int idx;string a;}s[maxn];
bool cmp(str a,str b){return a.a<b.a;}
bitset<maxn>ans;
char s1[maxn],s2[maxn];
signed main(){
freopen("dict.in","r",stdin);
freopen("dict.out","w",stdout);
int n=rd(),l=rd();
if(n==1){cout<<"1\n";return 0;}
for(int i=1;i<=n;++i)cin>>s[i].a,s[i].idx=i;
sort(s+1,s+n+1,cmp);
//for(int i=1;i<=n;++i)cout<<s[i].a<<' '<<s[i].idx<<'\n';
strcpy(s1,s[1].a.c_str());
ans[s[1].idx]=1;
for(int i=2;i<=n;i++){
strcpy(s2,s[i].a.c_str());
sort(s2,s2+l);
ans[s[i].idx]=(strcmp(s1,s2)>0);
}for(int i=1;i<=n;i++)cout<<ans[i];
cout<<'\n';
return 0;
}
两次 sort,我有点担心会爆,但大样例从头 clock 到尾 clock ,平均差700000(我以此猜测是不是以微秒为单位),估计能过。我放心了。
(但是有人说,CCF 这次可能会带着自己的心意,去卡 sort 。)
T2 三值逻辑
看起来十分甚至九分的简单,我怀着这种心态开了 T2。
9:20,我也不知道自己在干什么,迷迷糊糊开了两个数组,一个 sink 用来存储“汇”,一个 f 用来存储赋值语句中与汇的关系(正向反向),如果汇为 0,则恰巧表示 T , F 或 U.存储这些玩意就耗费了我近一个小时,中途还出现了一些奇妙的情况,如最后一个点的汇突然指向一个超出 n 的数,或第 0 个点突然出现了属于自己的汇。
存完了,然后就不知道该干啥了,忙活了半小时后,发现可以按照顺序,取汇的汇的汇的汇的汇……来判断是否存在“汇环”,有存在的话,如果引起矛盾,环上的点全部设为 U 。但是第二个样例始终过不去。我最后放弃想正解了,直接 dfs,中途也不是很顺利,在 lyr(递归层数标记)>n 时把 cnt 写成了 ncnt,结果一直没有输出。这告诉我,即便是深搜,也不是很好写。
开完后面两题后,我回来看 T2,发现第 3,4 个点很好写,v 可能的取值只有 TFU,那么意味着所有点的汇都是 0,很好写。于是我又写了这些点的代码,期望多得到 20 分,然后再也没管这一题。
(后来民间数据测试结果告诉我,第 66 行的 debug(n) 没删,痛失 20 分!!!因提交时调试代码未删净而彻底的寄掉了!!!)
#include<bits/stdc++.h>
#define I using
#define AK namespace
#define NOIP std
I AK NOIP;
inline int rd(){
int x=0,f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=((x<<3)+(x<<1)+(ch^48));
return x*f;
}const int maxn=1e5+5;
int f[maxn],sink[maxn];
bool vis[maxn];
int opt1[maxn],opt2[maxn],opt3[maxn],cnt,m;
//vector<int>src[maxn];
void debug(int n){
cout<<'\n';
for(int i=1;i<=n;++i)cout<<f[i]<<' ';
cout<<'\n';
for(int i=1;i<=n;++i)cout<<sink[i]<<' ';
cout<<'\n';
}int seq[maxn],a[maxn],n,ans;
void dfs(int lyr){
if(lyr>n){
int cntu=0;
for(int i=1;i<=n;i++)a[i]=seq[i];
for(int i=1;i<=cnt;i++){
if(opt1[i]==4)a[opt2[i]]=a[opt3[i]];
else if(opt1[i]==5)a[opt2[i]]=(a[opt3[i]]==2?2:a[opt3[i]]^1);
else a[opt2[i]]=opt1[i];
}for(int i=1;i<=n;i++){
if(a[i]!=seq[i])return;
cntu+=(a[i]==2);
}ans=min(ans,cntu);
return;
}for(int i=0;i<3;i++)seq[lyr]=i,dfs(lyr+1);
}signed main(){
freopen("tribool.in","r",stdin);
freopen("tribool.out","w",stdout);
int ptnum=rd(),datanum=rd();
while(datanum--){
n=rd(),ans=1e8;m=rd(),cnt=0;
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)sink[i]=i;
for(int i=1;i<=m;++i){
cnt++;
char ch=getchar();
if(ch=='T'||ch=='F'||ch=='U'){
int k=rd();
f[k]=(ch=='T'?0:ch=='F'?1:2);
opt1[cnt]=f[k],opt2[cnt]=k;
sink[k]=0;
}else{
int x=rd(),y=rd();
if(f[y]<2)f[x]=f[y]^(ch=='-');
else f[x]=2;
sink[x]=sink[y];
opt1[cnt]=(ch=='-')+4;
opt2[cnt]=x,opt3[cnt]=y;
}
}//for(int i=1;i<=cnt;i++)cout<<opt1[i]<<opt2[i]<<opt3[i]<<'\n';
if(ptnum<3){dfs(1);
cout<<ans<<'\n';}
else{
debug(n); //错误出在这里,忘记删了
ans=0;
for(int i=1;i<=n;i++)ans+=(f[i]==2);
cout<<ans<<'\n';
}
}cout<<'\n';
return 0;
}
T3 双序列拓展
这是啥?好吃吗?可以嚼的动吗?
为了避免你扔硬币蒙混过关?这是什么意思?
拿着黑笔和蓝笔,在考场上研究规律,显然本蒟蒻没有能力推出它们,只好退而求其次,寻 CCF 的部分分。即便如此,我也只写出了第一个点,第二个点我只祈求 CCF 的第二个点是 nm=2,而非 n=m=2(因为自己菜,写不出),这样就能得 10 分,多得 5 分。
其他的我连深搜都写不出来,如果我能写出来,那么其他巨佬一定也能写出来,甚至有更好的解法。
在windows环境下还来了个 CE(在 void solve 函数里面写了个 return 0),但愿 linux 不要让我 ce ,笔记考场上这段代码还是能正常运行的。
#include<bits/stdc++.h>
#define I using
#define AK namespace
#define NOIP std
I AK NOIP;
const int maxn=500005;
int c,n,m,q;
int x[maxn],y[maxn];
string ans;
inline int rd(){
int x=0,f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=((x<<3)+(x<<1)+(ch^48));
return x*f;
}void solve(){
if(c==1){ans+=(x[1]==y[1]?"0":"1");return;}
if(n==2&&m==1){ans+=((x[1]-y[1])*(x[2]-y[1])<=0?"0":"1");return;}
if(n==1&&m==2){ans+=((x[1]-y[1])*(x[1]-y[2])<=0?"0":"1");return;}
if(x[1]==y[1]){ans+="0";return 0;} //错误出在这里,return 0
if(c>=8&&c<=14){
}
}signed main(){
freopen("expand.in","r",stdin);
freopen("expand.out","w",stdout);
c=rd(),n=rd(),m=rd(),q=rd();
for(int i=1;i<=n;++i)x[i]=rd();
for(int i=1;i<=m;++i)y[i]=rd();
solve();
while(q--){
int kx=rd(),ky=rd(),k1,k2;
for(int i=1;i<=kx;i++)k1=rd(),k2=rd(),x[k1]=k2;
for(int i=1;i<=ky;i++)k1=rd(),k2=rd(),y[k1]=k2;
solve();
}cout<<ans<<'\n';
return 0;
}
T4 天天爱打卡
突然想起了 NOIP2016 的天天爱跑步?不过好像和这题挨不上一点边。
开这题时,已经是 12:20,本来想思考一下动规的状态转移方程的,但时间不允许。深搜,启动!!!void dfs(int lyr,int now,int nl)
深搜写的很快,lyr 表示层数(Layer 的缩写),now 表示当前连续的跑步天数,nl 表示当前的能量。在 lyr>n 时取nl最大值。写完后发现一个细节问题,截止时间为 x 的天数可能不止一个,而我是用一维数组存储对应关系。哎,接下来的事情我也改变不了,就看今年 CCF 的出数据工具是用手还是用脚了。
#include<bits/stdc++.h>
#define I using
#define AK namespace
#define NOIP std
#define hbx unordered_map //很明显,一开始我想hbx,但感觉不如一维数组
I AK NOIP;
const int maxn=100005;
int n,m,k,d;
struct tz{int x,y,v;}t[maxn];
bool cmp(tz a,tz b){return a.x<b.x;}
int tr[maxn]={0};
int seq[maxn],ans=0;
inline int rd(){
int x=0,f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=((x<<3)+(x<<1)+(ch^48));
return x*f;
}void dfs(int lyr,int now,int nl){
//cout<<'\n'<<lyr<<' '<<now<<' '<<nl;
if(lyr>n){
//for(int i=1;i<=n;i++)cout<<seq[i]<<' ';
ans=max(ans,nl);
return;
}if(now<k){
seq[lyr]=1;
if(tr[lyr]!=0&&t[tr[lyr]].y<=now+1)dfs(lyr+1,now+1,nl+t[tr[lyr]].v-d);
else dfs(lyr+1,now+1,nl-d);
}seq[lyr]=0,dfs(lyr+1,0,nl);
}signed main(){
freopen("run.in","r",stdin);
freopen("run.out","w",stdout);
int ptnum=rd(),datanum=rd();
while(datanum--){
memset(t,0,sizeof(t));
memset(tr,0,sizeof(tr));
memset(seq,0,sizeof(seq));
ans=-0x520ccf;
n=rd(),m=rd(),k=rd(),d=rd();
for(int i=1;i<=m;i++)t[i].x=rd(),t[i].y=rd(),t[i].v=rd();
sort(t+1,t+m+1,cmp);
for(int i=1;i<=m;i++)tr[t[i].x]=i;
dfs(1,0,0);cout<<ans<<'\n';
}
}
结尾
我粗略的检查了一下 T1 和所有题的 freopen,然后还打算玩盘贪吃蛇,但在监考老师的巡视中,“自信”的交了代码,拿着士力架的包装袋和未食用的八宝粥,沉重的离开了考场。
估分:100+20+5+8=133
于是乎,寄了。
同行四人中,一个九年级的,一个高一的,两个高二的,都估计拿到了超过 160 的分数。面对 T2 脑残挂的 20 分,我只留下无尽的感慨。
题目过于可怕,感觉该次比赛分数线可能比 CSPS 高。