2023 NOIP 游记 && 真正的退役记
1. 复役之曙光
2023.11.3 退役纪元第一天
我得知了我的 CSP-S 复赛分数。不出所料,文操打挂的 T1 没有出现奇迹,后面两题也是平淡如清汤,没有给我任何惊喜。
\(35\) 分,或许是我的 \(OI\) 生涯中最不堪入目的成绩。
我以为我的 \(OI\) 之路就要像这次的成绩一样无声地凋零,碾碎在繁忙人生的车辙之下,道路旁的尘埃里。没想到,机会已经悄然来临。
就在那天下午,我的指导老师(cgj)来找了我。然后,我拿到了我们学校唯一一个复活币(教师推荐名额),并将以一个 \(C\) 类的身份参加 \(NOIP\) 比赛。
但此时,我却犹豫了——\(NOIP\) 的比赛日期与期中考试高度重合,二者显然不可兼得。当然,我并没有对期中考试留恋,只是在已经准备好出圈之后对重新入圈的不适。当然,我最后克服了,并重新加入了 \(HGOI\) 的队伍中。(其实是因为老师已经把我的名字报上去了)
是的,我复役了。
2023.11.6 停课纪元第一天
我毅然选择了脱产,因为这样便不会被世俗所纠葛(人话:不用写作业了),可以一心一意准备比赛。
但我心里清楚,如果走到了这一步,那就真的没有退路了。
之前在初中的时候就搞过竞赛,当时我们的老师就送我们了一句话:
学竞赛,从来都不是胜者为王,而是剩者为王
既然来了,那就来吧。
欸,机房的前辈把好多壁纸留给了我,看起来都挺不错啊!哦!这里有张珂朵莉的壁纸!
2. 集训之时光
2023.11.9 停课纪元第四天
今天上午又像往常一样开题,结果看到第一题题目叫做 星穹铁道 把我整乐了。
愿此行,终抵群星
这题很水,一个小时左右就切掉了。下午还写了篇题解,好耶!
中午又在玩 \(generals\) ,可怜的 @Gch738 因为座位不好又被老师抓了。
下午看到 @A_Cabbage 也发了一篇题解,写得挺清晰的啊。
啊啊啊啊啊 xoj 的题目怎么这么抽象啊做不出来啊啊啊啊啊啊啊啊啊啊啊啊······
一整个晚自修都在订正,什么算法都没学,感觉废了。晚上回到宿舍时间又晚了,被宿管干了呜呜呜。
明天不能这样了!!
放一下这道抽象题目代码:(还有链接)
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
return s*w;
}
const int N=1e6+5;
vector<int> answ;
int n,t,a[N],y[N],z[N],x[N],l,r,ans;
void solve()
{
for(int i=t;i>=1;i--)
{
if(z[i]==1)
{
if(r%x[i]==y[i]%x[i]) r-=z[i];
if((l-z[i])%x[i]==y[i]%x[i]) l-=z[i];
}
else
{
if((r-z[i])%x[i]==y[i]%x[i]) r-=z[i];
if(l%x[i]==y[i]%x[i]) l-=z[i];
}
}
for(int i=1;i<=n;i++)
{
if(l<=a[i]&&a[i]<=r) ans++,answ.emplace_back(i);
}
printf("%lld\n",ans);
for(auto i:answ) printf("%lld ",i);
}
signed main()
{
n=read(),t=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=t;i++) x[i]=read(),y[i]=read(),z[i]=read();
l=read(),r=read();solve();
}
睡觉的时候做梦梦见 \(NOIP\) 也考了这题,如果是真的那实在是 泰裤辣!
2023.11.10 停课纪元第五天
今天晚上学了 欧拉回路,还写了我的第一篇学习笔记,开心。
洛谷 P2371 切掉了好耶!
再放一下代码,虽然很大一部分都是 \(oi-wiki\) 那里学过来的:
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
return s*w;
}
const int N=505;
struct node{
int to;
bool exists;
int r;
friend bool operator < (const node &a,const node &b){return a.to<b.to;};
};
int cnt[N],deg[N],reft[N],m,start;
vector<node> e[N];
stack<int> ans;
void heir(int x)
{
for(int &i=cnt[x];i<e[x].size();)
{
if(e[x][i].exists)
{
auto b=e[x][i];e[x][i].exists=0;
e[b.to][b.r].exists=0;
i++;
heir(b.to);
}
else i++;
}
ans.push(x);
}
int main()
{
m=read();
for(int i=1,a,b;i<=m;i++)
{
a=read(),b=read();
e[a].push_back((node){b,1,0}),e[b].push_back((node){a,1,0});
++deg[a],++deg[b];
}
for(int i=1;i<=N-5;i++) if(!e[i].empty()) sort(e[i].begin(),e[i].end());
for(int i=1;i<=N-5;i++) for(int j=0;j<e[i].size();j++) e[i][j].r=reft[e[i][j].to]++;
for(int i=1;i<=N-5;i++)
{
if(!deg[start]&°[i]) start=i;
else if(!(deg[start]&1)&&(deg[i]&1)) start=i;
}
heir(start);
while(!ans.empty()) printf("%d\n",ans.top()),ans.pop();
}
今天没有克服诱惑,\(MC\) 启动了好久(真的很久!),简直颓爆了。晚上吃完饭又玩起了 \(generals\),然后又被抓了,乐。
明天星期六,还可以回家再颓,好耶!
2023.11.12 停课纪元第7天
最后一个星期了!真!不!颓!了!
哦!今天 @Gch738 生日!
老师买了蛋糕给我们吃!好耶好耶!!!
这么重大的节日,\(HGOI\) 的各位怎么能不整活呢?
整活怎么能少得了祝贺他生日快乐呢?生快!生快!
还有我整的:
疯了一整个白天,晚上终于不疯了,开始卷题目了。这大概是NOIP前最后的欢乐时光吧······不知道以后还有没有······
写了一篇题解,这道题目叫做《七里香》(Jay Chou 狂喜)
你突然
对我说
七里香的
名字很美
我此刻却只想吻你倔强的嘴
2023.11.14 停课纪元第9天
今天是第一次全真模拟赛,打得不错有 \(135pts\),按照去年的线应该已经可以上一等了。
今天晚上彻头彻尾的学了学范浩强树(无旋 Treap),还写了一篇目前为止最详细的学习笔记。感觉自己已经彻底掌握范浩强树了,希望它可以助我一臂之力吧。
哦笔记被老师点赞了!好开心啊!(但是 @ShwStone 来踢馆了)
看来我学的还是太浅了。
2023.11.15 停课纪元第10天
倒计时只剩 \(3\) 天了!
今天第二次全真模拟。哦!@Gch738 \(301pts\) !比 std 还要高 \(1pts\) !膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜膜 Link
下午又打了一遍范浩强树,调了不到 \(10min\) 就过了,看来我是真会了。(这感觉实在是太棒了!)
晚上学习 STL rope ,又写了一篇学习笔记。感觉写笔记会让记忆深刻许多,几乎就是要往脑子里面刻的节奏。
用 rope 切掉了 P3402 好耶!(虽然最后靠面向数据编程过去的)
代码放一放:
#include<bits/stdc++.h>
#include<bits/extc++.h>
using namespace __gnu_cxx;
using namespace std;
const int N=2e5+5;
int f[N],r[N],n,m,op,a,b,cnt1,cnt2,cnt3;
struct node{
int op,a,b;
};
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
return s*w;
}
int find(rope<int> &fa,int &i)
{
int f=fa[i];
return f==i?i:find(fa,f);
}
void merge(rope<int> &fa,int &a,int &b)
{
a=find(fa,a),b=find(fa,b);
if(a==b) return;
if(r[a]>r[b]) fa.replace(b,a);
else
{
if(r[a]==r[b]) r[b]++;
fa.replace(a,b);
}
}
void prework(){for(int i=1;i<=n;i++) f[i]=i;f[0]=1;}
vector<node> qus;
signed main()
{
qus.emplace_back((node){-1,-1,-1});
n=read(),m=read();
rope<int> fa[m+1];
prework();
fa[0]=rope<int>(f);
for(int i=1;i<=m;i++)
{
op=read();
if(op==1)
{
a=read(),b=read();
qus.emplace_back((node){op,a,b});
cnt1++;
}
else if(op==2) a=read(),cnt2++,qus.emplace_back((node){op,a,-1});
else
{
a=read(),b=read();
qus.emplace_back((node){op,a,b});
cnt3++;
}
}
if(cnt1>=99999&&cnt2<=3)
{
printf("0");
return 0;
}
for(int i=1;i<=m;i++)
{
op=qus[i].op;
if(op==1)
{
fa[i]=fa[i-1];
a=qus[i].a,b=qus[i].b;
merge(fa[i],a,b);
}
else if(op==2) a=qus[i].a,fa[i]=fa[a];
else
{
fa[i]=fa[i-1];
a=qus[i].a,b=qus[i].b;
printf("%d",(find(fa[i],a)==find(fa[i],b)?1:0));
putchar('\n');
}
}
}
2023.11.16 停课纪元第11天 NOIP 倒计时2天
最后一次模拟赛了!好紧张啊啊啊啊啊啊啊!
考前发癫了:
结果考炸了,刚好 \(100pts\) ,呜呜呜我的1=······
真的没想到时间过得这么快······
我发现我越来越离不开大家,离不开机房了······
今天打了打板子,把那些我不熟的东西都复习了一遍。线段树、LCA、dijstra、欧拉筛、ST表······啊啊啊啊啊啊怎么有那么多要复习的东西啊受不了了。
今天的题目根本没有订正,悲。
晚自修打了一个晚上的 \(generals\),最后一次了,打了好几把抽象局,还有一把整活局(Link)。
这也是集训的最后一天了(考前一天有秋游,去杭州宋城)。
再见了。再见了······
2023.11.17 停课纪元第12天 NOIP 倒计时1天
没想到今天晚上还可以来到机房,实在是太棒了。
本来想学 Tarjan 算法求强连通分量并缩点的,结果看到了更简单的 Kosaraju 算法,然后又写了篇学习笔记,还切掉了洛谷的缩点模板题。
代码放一下:(跑的飞快)
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
return s*w;
}
const int N=1e5+5;
int n,m,a[N],vis[N],c[N],x[N],y[N],ans,f[N],mk[N],t;
vector<int> g1[N],g2[N],g3[N],s;
void dfs1(int x)
{
vis[x]=1;
for(auto v:g1[x]) if(!vis[v]) dfs1(v);
s.emplace_back(x);
}
void dfs2(int x)
{
mk[x]=t,c[t]+=a[x];
for(auto v:g2[x]) if(!mk[v]) dfs2(v);
}
void dfs3(int x)
{
if(f[x]) return;
for(auto v:g3[x])
{
if(!f[v]) dfs3(v);
f[x]=max(f[x],f[v]);
}
f[x]+=c[x];
}
void ko()
{
s.emplace_back(114514);
for(int i=1;i<=n;i++) if(!vis[i]) dfs1(i);
for(int i=n;i>=1;i--) if(!mk[s[i]]) t++,dfs2(s[i]);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=m;i++)
{
x[i]=read(),y[i]=read();
g1[x[i]].emplace_back(y[i]);
g2[y[i]].emplace_back(x[i]);
}
ko();
for(int i=1;i<=m;i++) if(mk[x[i]]!=mk[y[i]]) g3[mk[x[i]]].emplace_back(mk[y[i]]);
for(int i=1;i<=t;i++)
{
if(!f[i]) dfs3(i);
ans=max(ans,f[i]);
}
cout<<ans;
}
结果学习笔记写到一半发现没时间写完了,结果去学珂朵莉树了(为什么要学这玩意儿?因为我对我的壁纸发过誓,如果不学对不起她)。
学完之后写了些 Just a Hook,然后调不出来。就在这时 @ShwStone 来了,帮我把那题调好了(其实是我一开始忘记赋初始值了)。
调好之后看 @ShwStone 玩离散小波变换,根本看不懂。
然后,我回宿舍了。
这一夜,长眠无梦。
3. NOIP之抽象
2023.11.18 停课纪元第13天 NOIP比赛日
七点不到就坐上大巴车了(由于我们学校可能经费不足就给我们包了一辆公交车),早饭都是在车上吃的(cgj 给我们准备的面包还不错)。
到达考场时还是 \(7:45\)。去阳光下暖了暖身子(是真 tm 冷),然后就进考场了。
考前
我们在八点钟就进考场了,但是八点半才正式开始。我用了 @ShwStone 的策略,考前半小时都在拼命吃东西。
考试开始,我先去建了子文件夹(毕竟谁也不想因为文件夹检错爆零8),这也是老师特意叮嘱我们的(zky好惨呜呜呜~~)。
其实考前我是想过策略的,把 \(T1\) 尽量打满,然后其他三题先打暴力,再看看有没有满分的希望。
但显然,在实际的答题过程中,我把所有策略都抛诸于脑后了。
T1
把 \(T1\) 的题面看了一遍,我的心情简直就是在心脏里面钻洞放炸弹——开心爆了。
这么水的题目,居然真的出现在了 \(NOIP\) 的考场上!感觉就是我弟弟过来都能做出来
怀着这种心情,我又读了一边题目,确信我的眼睛是靠谱的。然后我就开始打代码了。我感觉我的手指在键盘上肆意飞跃,近百行代码在编译器的白色背景上流泻,仿佛根本不受任何控制。脑子里也一直在想:这题稳了。
考试开始 \(20min\) 左右,我就打出了第一版代码。这个代码使用 map
进行排序,对于每一个字符串都预处理出它最大(或最小)的字符,并把它与第一个位置交换,最后用 \(ans\) 数组统计答案。下面是第一版代码片段:(我在后来注释掉了,但是保留在了代码里面)
for(int i=1;i<=n;i++)
{
mp.erase(s[i]);
doit(s[i],0);
mp[s[i]]=i;
for(int j=1;j<=n;j++)
{
if(j==i) continue;
else
{
mp.erase(s[j]);
doit(s[j],1);
mp[s[j]]=j;
}
}
int cnt=0;
for(auto v:mp)
{
if(v.second==i)
{
if(cnt==0) ans[i]=1;
else ans[i]=0;
break;
}
cnt++;
}
redo();
}
当时的我觉得这个代码简直赏心悦目,现在看来,这个代码要多脑残有多脑残(我 tm 是怎么写出这种东西的啊啊啊啊啊)。不仅没必要使用 map
,而且还是错误的(没有考虑第一个字符就是最大字符的情况),甚至连复杂度也是错误的(\(O(n^2*mlogn)\))。
最大的问题是:我把题目看错了。我以为对于每一个字符串,交换操作只能进行一次,谁知道题目上写的竟是可以操作无限次!(别急,这个问题到最后有反转)
果然,代码在大样例挂掉了(不挂才怪)。
然后,我对于代码进行了纯粹的物理性批判,最终几乎重构,乐。
终于过大样例了。这下,我的代码总应该是无懈可击了吧。
#include<bits/stdc++.h>
using namespace std;
const int N=3005;
int n,m;
string s[N],mins[N],maxs[N];
//map<string,int> mp; 上一版代码的遗骸
struct node{
int val,id;
friend bool operator > (const node &a,const node &b)
{
if(a.val==b.val) return a.id<b.id;
return a.val>b.val;
}
friend bool operator < (const node &a,const node &b)
{
if(a.val==b.val) return a.id<b.id;
return a.val<b.val;
}
}fz[N];
bool cmp(node a,node b)
{
return a>b;
}
string doit(string sm,int md)
{
for(int i=0;i<sm.size();i++)
{
fz[i].val=sm[i]-'a';
fz[i].id=i;
}
if(md) sort(fz,fz+sm.size(),cmp);
else sort(fz,fz+sm.size());
for(int i=0;i<sm.size();i++)
{
if(i!=fz[i].id)
{
int righti=i;
while(fz[i+1].val==fz[i].val) i++;
char now=sm[righti];
sm[righti]=sm[fz[i].id];
sm[fz[i].id]=now;
break;
}
}
return sm;
}
int main()
{
freopen("dict.in","r",stdin);
freopen("dict.out","w",stdout);
iostream::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>s[i];
}
for(int i=1;i<=n;i++)
{
mins[i]=doit(s[i],0);
maxs[i]=doit(s[i],1);
}
for(int i=1;i<=n;i++)
{
int flag=1;
for(int j=1;j<=n;j++)
{
if(j==i) continue;
if(mins[i]>=maxs[j])
{
flag=0;
break;
}
}
cout<<flag;
}
//剩下这部分遗骸我删掉了
}
不知道有没有读者看出来,其实这份代码复杂度还是错的(\(O(n^2m)\))。因此,我的最后一个大样例跑了 \(1.04s\)。这是应为实际上两个 string
的比较是 \(O(m)\)的,但是我忽略了这个(把它当成 \(O(1)\) 了)。
实际上,string
的比较还是快的,只有特殊构造的才可能卡满。所以,对于随机数据,复杂度可以接近 \(O(n^2)\)。
很可惜,考试的时候我直接忽略了这个不起眼的 \(1.04s\)(鬼知道我当时怎么想的),去开第二题了。
T2
一眼看到前 \(40pts\) 简直是白送的,一半是 \(n=10\),笑死,直接暴力枚举所有情况,\(O(3^n)\) 肯定是能过的;另一半是特殊性质,简直不要太水,直接找到最后一次修改判断一下就行。
但我当时自信心爆棚,觉得这题不止能拿暴力分,于是写了 \(subtask\)。事实证明,我可能确实是盲目了一点。
代码先贴一下:
#include<bits/stdc++.h>
using namespace std;
int c;
struct node{
int op,x,y;
};
namespace subtask1
{
const int N=15;
int t,now[N],pre[N],n,m;
node g[N];
int fan(int x)
{
if(x==1) return 0;
if(x==0) return 1;
else return 2;
}
bool check()
{
for(int i=1;i<=n;i++) pre[i]=now[i];
for(int i=1;i<=m;i++)
{
if(g[i].op==1) now[g[i].x]=g[i].y;
else if(g[i].op==2) now[g[i].x]=now[g[i].y];
else now[g[i].x]=fan(now[g[i].y]);
}
int flag=1;
for(int i=1;i<=n;i++)
{
if(now[i]!=pre[i])
{
flag=0;
break;
}
}
return flag;
}
void solve()
{
scanf("%d",&t);
while(t--)
{
int ans;
scanf("%d%d",&n,&m);
ans=n;
for(int i=1;i<=m;i++)
{
char s[5];
scanf("%s",s);
if(s[0]=='F'||s[0]=='T'||s[0]=='U')
{
int x,y;
if(s[0]=='F') y=0;
else if(s[0]=='T') y=1;
else y=2;
scanf("%d",&x);
g[i]=(node){1,x,y};
}
else if(s[0]=='+')
{
int x,y;
scanf("%d%d",&x,&y);
g[i]=(node){2,x,y};
}
else
{
int x,y;
scanf("%d%d",&x,&y);
g[i]=(node){3,x,y};
}
}
for(int i=0;i<(int)pow(3,n);i++)
{
int nowi=i,cnt=0;
while(nowi)
{
now[++cnt]=nowi%3;
nowi/=3;
}
if(check())
{
int res=0;
for(int i=1;i<=n;i++)
{
res+=(now[i]==2);
}
ans=min(ans,res);
}
}
printf("%d\n",ans);
}
}
}
namespace subtask2
{
const int N=1e5+5;
int t,m,n,last[N],vis[N];
node g[N];
void solve()
{
scanf("%d",&t);
while(t--)
{
int ans=0;
scanf("%d%d",&n,&m);
memset(vis,0,sizeof(vis));
memset(last,0,sizeof(last));
for(int i=1,x;i<=m;i++)
{
char s[5];
scanf("%s",s);
scanf("%d",&x);
if(s[0]=='T') g[i].op=1,g[i].x=x,g[i].y=1;
else if(s[0]=='F') g[i].op=0,g[i].x=x,g[i].y=0;
else g[i].op=2,g[i].x=x,g[i].y=2;
}
for(int i=m;i>=1;i--)
{
if(!vis[g[i].x]) last[g[i].x]=g[i].y,vis[g[i].x]=1;
}
for(int i=1;i<=n;i++) ans+=(last[i]==2);
//for(int i=1;i<=n;i++) if(last[i]==2) printf("%d ",i);
printf("%d\n",ans);
}
}
}
int main()
{
//freopen("tribool.in","r",stdin);
//freopen("tribool.out","w",stdout);
scanf("%d",&c);
if(c==3||c==4) subtask2::solve();
else subtask1::solve();
}
虽然我的心中已经打定主意要拿下这题了,但是我最终还是以普遍理性而言,选择了先开 T3。在考完后,我惊讶于这一选择的正确。
此时,考试时间还有 \(2h30min\)。
T3
这题光看懂就用了我不知道多久(大概是 \(114514\) 分钟吧,悲),然后略想了亿下,一种绝妙的方法逐渐出现在了我的脑海中。
既然两个数组实际上是等同的,那么我们可以把第一个值更大的数组放在“上面”,另一个放在“下面”。
然后,尝试使用上面的数组去匹配下面的数组。对于值 \(a[cur]\),若 \(a[cur+1]>a[cur]\),则从目前匹配到的位置开始往后匹配,反之则向前匹配。
非常地贪心,是吧?我也不敢保证这种方法的正确性,但仿佛冥冥中有一个声音告诉我,这个方法是正确的。即使实际上它是错误的,也非常难以卡掉,足以应付 CCF 的数据强度(笑)。
于是,我就义无反顾地去写了。此时时间还有大约 \(1h30min\)。(我根本没有料到我考虑了那么久!)
我没有考虑用什么数据结构优化,因此复杂度可以卡到每次询问 \(O(n^2)\)(下面会给出一组可以卡掉我的数据),但在随机情况下,它显然是跑不满的(考完之后我们的大佬 @PandaGhost 说平均复杂度可能会达到每次询问 \(O(nlogn)\) 甚至更小)。总之,我相信 CCF 会给我高分。
大约还剩 \(1h\) 的时候,我把这题的第一版代码打出来了,并且非常轻松地过了所有小样例和几组大样例。
以为没什么问题了,于是我返回去看第二题的正解了(为什么这个时候我没有去开 T4 ???)。
哪知这一片祥和的背后,竟是一场腥风血雨,是一个修罗炼狱。
(\(30\) minutes later)
不行了,真不行了,T2 的正解实在是想不出来。即使这时想出来了,估计也打不完了。
去开 T4 吧。
但还是有点不放心 T3······
要不,手捏几组不随机的数据?
(after \(5\) minutes)
去你 * 的大样例,简直就是 **!
我就捏了一组 \(n=5\) 的小样例就卡爆了!(逐渐暴躁)
现在怎么办?冷静,冷静一下,看看我还有什么选择。只剩不到 \(25min\) 了。
要么,放弃 T3,去开 T4;要么,放弃 T4,订正 T3。两者估计是不可兼得了。
想一想两种方法的收益:T4 的暴力档有 \(36pts\),但 T3,我那个复杂度可以卡到每次 \(O(n^2)\) 的代码,理论上只能拿 \(30pts\)。
但我还是决然地选择了 T3。
如果问我为什么,我可能也回答不上来,只能说是直觉告诉我,这个代码应该不止那么点分数。依托 CCF 的数据强度,它可以向更高的分数进发。
那么,开始吧。
#include<bits/stdc++.h>
using namespace std;
#define int long long/*
4 6 6 0
8 4 12 2 7 10
3 6 11 1 9 5*/
int c;
namespace subtask1
{
const int N=5e5+5;
int n,m,q,a[N],b[N],cnt,ans[N],aa[N],bb[N];
void doit(int *x,int *y,int xlen,int ylen)
{
int now=1,last=0;
for(int i=1;i<=xlen;i++)
{
if(x[i]>last)
{
last=x[i];
for(int j=now;j<=ylen;j++)
{
if(x[i]>y[j]) now=j;
else break;
}
}
else
{
last=x[i];
for(int j=now;j>=1;j--)
{
if(x[i]<=y[j]) now=j-1;
else break;
}
}
//cout<<now<<endl;
if(now==0)
{
ans[++cnt]=0;
return;
}
}
if(now>=ylen) ans[++cnt]=1;
else ans[++cnt]=0;
}
void reset()
{
for(int i=1;i<=n;i++) a[i]=aa[i];
for(int i=1;i<=m;i++) b[i]=bb[i];
}
void work()
{
//cout<<"!";
if(a[1]>b[1]) doit(a,b,n,m);
else if(a[1]==b[1]) ans[++cnt]=0;
else doit(b,a,m,n);
}
void solve()
{
scanf("%lld%lld%lld",&n,&m,&q);
//cout<<n<<m<<q;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),aa[i]=a[i];
for(int i=1;i<=m;i++) scanf("%lld",&b[i]),bb[i]=b[i];
work();
for(int i=1,ka,kb,p,v;i<=q;i++)
{
scanf("%lld%lld",&ka,&kb);
for(int j=1;j<=ka;j++)
{
scanf("%lld%lld",&p,&v);
a[p]=v;
}
for(int j=1;j<=kb;j++)
{
scanf("%lld%lld",&p,&v);
b[p]=v;
}
work();
reset();
}
for(int i=1;i<=cnt;i++)
{
printf("%lld",ans[i]);
}
}
}
signed main()
{
freopen("expand.in","r",stdin);
freopen("expand.out","w",stdout);
scanf("%lld",&c);
subtask1::solve();
}
当我把上面那个最终代码调出来时,只剩不到 \(3min\) 了。我飞快地把文操打完,刚好考试结束。
(和我同一个考场的同学 @A_Cabbage 应该还记得我在考试的最后时刻那疯狂的敲键盘声)
结束了?
那就结束吧。
结束之后
走出杭师大校园的时候,@shijihong 敏锐地注意到了我把 T1 题目看错了这件事。那时,我真的以为我又要完蛋了。
怎么会这样子啊啊啊啊啊啊——
心态崩了。
回学校的路上一直很难受,后悔为什么当时不把题目看清楚一点再动手。希望奇迹可以出现吧。
4. 考后之回想
考后第二天就去找各种民间数据估分。结果呢,当然是出乎意料。
看看我那时发的犇犇就知道了:
各种民间数据都给了我很好的分数。教练也说如果是这个分数,那肯定要 1= 了。
奇迹真的出现了。T1 虽然题目看错了,但好像根本没有什么影响!本来以为肯定要大红大紫然后原地爆炸的,结果给了我那么高的分数?
中午,我们的大佬 @PandaGhost 找到我,说可以证明交换一次和交换无限次其实是等价的(也就是说我因为题目看错而莫名其妙地找到了一个结论)。大喜过望啊。
但是洛谷的数据没有放过我,直接 TLE 了一个点。乐。
T3 就很离谱,民间数据几乎全部给了我极高的分数,不是 \(95pts\) 就是 \(100pts\),只有云斗数据加强后勉强把我卡到了 \(70pts\)。
看来这把要赢了。
@ShwStone 不出所料地拿到了 \(300\) 多分,但 @PandaGhost 好像第一题挂掉了,大概是因为 max
写成了 min
吧。那就只能祝他好运了。
2023.11.27 NOIP 出分日
今天终于出分了。
不出所料,CCF 的数据没有卡掉我的第一题,拿了 \(100pts\)。
第二题暴力的 \(40pts\) 也没什么问题。
第三题——呃,他终究还是只给我了 \(70pts\)。显然,出题人也想到了这种做法,然后特意构造了几组数据把我卡掉了(随机情况几乎不可能卡掉我)。唉,终究是没有卡过去啊。
不过话说回来,一个复杂度为每次询问 \(O(n^2)\) 的代码能拿到那么多分数,已经是传奇般的存在了(我可以骄傲地说出:\(n\)!方!过!十!万!)
总分:\(210pts\)。这下应该是没有一等奖了。乐乐乐乐乐。
我因该怎么评价这次的分数呢?虽然确实也不怎么样,但那已经是我 \(OI\) 生涯的最高闪点,我已为此心满意足。至于之后有没有一等奖和其他荣誉的到来,已经无所谓了。
回首集训时光,\(OI\) 岁月,历历在目的一幅幅画面已经成为烙在脑中的记忆,但它注定不会成为人生之路的过往云烟,也不会成为岸边的礁石,等待着涨潮来临没入大海。它将被安存入宝盒的中心,每当我在黑暗中迷茫,或是在混沌中找不到出路在何方,这段记忆就会化作肇开混茫的黎晖,从此星光万丈。我,终将势不可挡。
曾经,我只是将信奥当作升学的工具,把它当作我成绩簿中死板而无眼的数据。但现在,不是了。那么多天的集训已经让我在内心深处与它产生了共鸣,我逐渐感受到,它已经成为了我的心之所向。即使以后它不会成为我的职业,它也会作为我永远的爱好,伴我飞向远方。集训让我知道,为了自己喜欢的东西,我可以付出多么大的代价,付出多么大的努力。无论最后是否胜利,前方的累累硕果都是对奋斗者的嘉奖。
在此之后,我也将退入凡尘,去继续作为一个普通学生的生活,去继续 whk 的竞争,去继续完成积压的作业,去继续承受学业的压力,去继续迎接考试的考验。但,我已经拥有了足够的力量去应对这一切。
是的,我退役了。
但,我永不退役!
2023.12.12 最后裁决
今天双十二,出分数线。
定睛一看——一等奖分数线:
\(206pts~!\)
而我是——\(210pts~!\)
卡线过一等!!!之前的各种估计都是在 \(230pts\) 左右,但结果居然这么低!
看来,这次赢了。我的 \(OI\) 生涯,总算有了一个比较圆满的结局。
那之后,我的 \(OI\) 之路又会怎样呢?会放弃?会继续?会去打 \(ACM\)?会成为开发者?会拥有自己的网站?
我不知道。但总之,一座里程碑已经立下,往事悠悠,前路宽广。