CSP-S2025游记
Update on 2025.11.7:改正了游记中的错误,更新各题考场代码和分数,少量修改了细节内容。
Update on 2025.11.9:更新了题面。
前言
本文中为满足整体观感,部分区域未采用标准格式。
初赛不说了,88 分,第一次提高组初赛做这么爽。
赛前
6:10 左右起床,吃完金拱门大概 6:40 赶到学校。虚晃一枪,然后逃掉早读溜去机房,路上还遇到了隔壁班班主任兼我们的英语老师,差点被 gank。
到机房晨读树状数组、线段树、Tarjan、最短路还有 KMP(可惜考场上没想到怎么用)。大概 1 个小时这样后开始刷 b 站后来还开了把王者。
9:00 这样就出发了,路上又打了几把王者睡了会儿觉,还给 bjx 大佬拍了合影,想看的私我。
11:30 到杭州,下车以后呈游离态寻找食物。和几个同学一起去了一家黄焖鸡的饭店,那个茄子还怪好吃的(雾
和 bjx 点了菜 AA 下来每人 18.5,总的来说还是肥肠有性价比的。bjx 大佬甚至吃饭的时候都还要给他姐调题,太卷了喵。哦对了,还有 bjx 超绝视角的帅照,想看私我。
过了一会儿吧,和组织失联了,本来准备去喝 luckin coffee,后来还是决定去找波(老师)。找到后她居然让我们做 J 组 T3 和 T4,看到题目两眼一黑,大概就只会暴力和特殊性质,就感觉 S 组已经没希望了。当然像波这种超标的口胡选手肯定是 2 分钟一道直接胡完了。
1:30 集合,然后就 balabala 到考场了(实名举报波带领大约 30 人闯红灯)。进校门时波直接被保安拦下来质问身份,波拼尽全力无法战胜,最后还是我和 bjx 出面解围喵。笑嘻了哈哈哈哈哈哈哈哈。
还有,你知道把考试袋从书包里拿出来时发现上面沾满了像粑粑一样的巧克力酱时的绝望吗……
手机开机放口袋(bushi
赛时
刚坐下没多久坐我右边的社恐(社交恐怖分子)问我借笔(骗你的,其实压根没还),问我多大了,后来还问我是不是前年 NOI 金牌(重名的)。抽象。
T1
看到题目第一时间想到的并不是 DP(这和大部分人貌似不太一样),而是一种接近正解但错误的贪心:当人数等于限制时,每次放入的元素与原序列中价值最小的元素交换。
想了差不多 5 分钟,然后写了大约 20 分钟,确定了这个想法时错误的,遂决定重构。当时也不是很崩溃,毕竟我原本的目标是在 2 个小时以内写完 T1。
其实 OI 比赛灵光乍现还是挺重要的,重构的时候一开始想到了用 priority_queue 维护 3 个序列(复习的时候优先队列做多了导致的)。由此又想到了在原贪心一个个放入的基础上先每次挑选最大值维护
最终单组询问时间复杂度
算上试错和调试大约花了 50 分钟,5 分钟时间调整了一下状态开始写 T2。
::::info[题面]
题目描述
小 L 是学校算法协会的成员。在今年的学校社团招新中,小 L 一共招收了
算法协会共设有三个部门,其中第
小 L 不希望某一个部门的新成员数量过多。具体地,他要求在分配方案中,不存在一个部门被分配多于
输入格式
本题包含多组测试数据。
输入的第一行包含一个正整数
接下来依次输入每组测试数据,对于每组测试数据:
- 第一行包含一个正整数
n ,表示新成员的数量。 - 第
i+1 (1 \leq i \leq n ) 行包含三个非负整数a_{i,1}, a_{i,2}, a_{i,3} ,分别表示第i 个新成员对第1,2,3 个部门的满意度。
输出格式
对于每组测试数据,输出一行一个非负整数,表示满足小 L 要求的分配方案的满意度的最大值。
输入输出样例 #1
输入 #1
3
4
4 2 1
3 2 4
5 3 4
3 5 1
4
0 1 0
0 1 0
0 2 0
0 2 0
2
10 9 8
4 0 0
输出 #1
18
4
13
说明/提示
【样例 1 解释】
该样例共包含三组测试数据。
对于第一组测试数据,可以将四个新成员分别分配到第
对于第二组测试数据,可以将四个新成员分别分配到第
对于第三组测试数据,可以将两个新成员分别分配到第
【样例 2】
见选手目录下的
该样例满足测试点
【样例 3】
见选手目录下的
该样例满足测试点
【样例 4】
见选手目录下的
该样例满足测试点
【样例 5】
见选手目录下的
该样例满足测试点
【数据范围】
对于所有测试数据,保证:
-
-
- 对于所有
1 \leq i \leq n ,1 \leq j \leq 3 ,均有0 \leq a_{i,j} \leq 2 \times 10^4 。
::cute-table{tuack}
| 测试点编号 | 特殊性质 | |
|---|---|---|
| 无 | ||
| ^ | ||
| ^ | ||
| ^ | ||
| B | ||
| ^ | 无 | |
| A | ||
| ^ | B | |
| ^ | C | |
| ^ | 无 |
特殊性质 A:对于所有
特殊性质 B:对于所有
特殊性质 C:对于所有
::::info[Code(100pts)]
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int a,b,c,mu;
}x[100005];
bool cmp(Node a,Node b)
{
return a.mu>b.mu;
}
Node t[4][100005];
int main()
{
freopen("club.in","r",stdin);
freopen("club.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
int T,n;
cin>>T;
while(T--)
{
cin>>n;
int maxn=(n>>1);
int i;
long long ans=0;
int cnt[4]={0,0,0,0};
for(i=1;i<=n;i++)
{
cin>>x[i].a>>x[i].b>>x[i].c;
if(x[i].a>=x[i].b&&x[i].a>=x[i].c)
{
ans+=x[i].a;
x[i].mu=x[i].a-max(x[i].b,x[i].c);
t[1][++cnt[1]]=x[i];
}
else if(x[i].b>=x[i].a&&x[i].b>=x[i].c)
{
ans+=x[i].b;
x[i].mu=x[i].b-max(x[i].a,x[i].c);
t[2][++cnt[2]]=x[i];
}
else
{
ans+=x[i].c;
x[i].mu=x[i].c-max(x[i].a,x[i].b);
t[3][++cnt[3]]=x[i];
}
}
for(i=1;i<=3;i++)
{
if(cnt[i]>maxn)
{
sort(t[i]+1,t[i]+cnt[i]+1,cmp);
int x=0;
while(cnt[i]>maxn)
ans-=t[i][cnt[i]--].mu;
break;
}
}
cout<<ans<<'\n';
}
return 0;
}
//Happy,meow.I think this is right.
::::
T2
粗读了一下题意,感觉像最小生成树,思考了一下执行城市化对树上边权的影响,但并没有想到正解。看到特殊性质后决定把
T2 花的时间还挺多的,大概有 1 个小时,可惜最后特殊性质没调出来。
::::info[题面]
题目描述
C 国的交通系统由
然而,近期由于一场大地震,所有
为尽快恢复城市间的交通,C 国政
输入格式
输入的第一行包含三个非负整数
输入的第
输入的第
输出格式
输出一行一个非负整数,表示将原有的
输入输出样例 #1
输入 #1
4 4 2
1 4 6
2 3 7
4 2 5
4 3 4
1 1 8 2 4
100 1 3 2 4
输出 #1
13
说明/提示
【样例 1 解释】
C 国政
【样例 2】
见选手目录下的
该样例满足测试点
【样例 3】
见选手目录下的
该样例满足测试点
【样例 4】
见选手目录下的
该样例满足测试点
【数据范围】
对于所有测试数据,保证:
-
- 对于所有
1 \leq i \leq m ,均有1 \leq u_i, v_i \leq n ,u_i \neq v_i 且0 \leq w_i \leq 10^9 ; - 对于所有
1 \leq j \leq k ,均有0 \leq c_j \leq 10^9 ; - 对于所有
1 \leq j \leq k ,1 \leq i \leq n , 均有0 \leq a_{j,i} \leq 10^9 ; - 任意两座原有的城市都能通过若干条原有的道路相互到达。
::cute-table{tuack}
| 测试点编号 | 特殊性质 | |||
|---|---|---|---|---|
| 无 | ||||
| A | ||||
| ^ | ^ | ^ | 无 | |
| ^ | ^ | A | ||
| ^ | ^ | ^ | 无 | |
| ^ | ^ | A | ||
| ^ | ^ | ^ | 无 | |
| ^ | A | |||
| ^ | ^ | ^ | 无 | |
| ^ | ^ | ^ |
特殊性质 A:对于所有
::::info[Code(32pts)]
/*#include<bits/stdc++.h>
using namespace std;
struct Edge
{
int u,v,w;
}e[1000005];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int fa[10005];
int c[10005];
int a[10005];
int ee[10005][10005];
int fid(int a)
{
if(fa[a]==a)
return a;
return fa[a]=fid(fa[a]);
}
void merge(int u,int v)
{
u=fid(u);
v=fid(v);
fa[u]=v;
}
int main()
{
//freopen("road3.in","r",stdin);
//freopen("road.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,k,i,j;
long long ans=0;
cin>>n>>m>>k;
for(i=1;i<=n;i++)
fa[i]=i;
for(i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
e[i].u=u,e[i].v=v,e[i].w=w;
}
for(i=1;i<=k;i++)
{
int x=0;
cin>>c[i];
for(j=1;j<=n;j++)
{
cin>>a[j];
if(a[j]==0)
x=j;
}
if(x)
{
for(j=1;j<=n;j++)
ee[x][j]=a[j];
}
}
sort(e+1,e+m+1,cmp);
int cnt=n-1;
for(i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v;
if(fid(u)!=fid(v)
{
ans+=min(e[i].w,min(ee[u][v]?ee[u][v]:1000000007,ee[v][u]?ee[v][u]:1000000007));
merge(u,v);
if(!(--cnt))
break;
}
}
cout<<ans<<'\n';
return 0;
}
*/
#include<bits/stdc++.h>
using namespace std;
struct Edge
{
int u,v,w;
}e[1000005];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int fa[10005];
int c[10005];
int a[10005];
//int ee[10005][10005];
int fid(int a)
{
if(fa[a]==a)
return a;
return fa[a]=fid(fa[a]);
}
void merge(int u,int v)
{
u=fid(u);
v=fid(v);
fa[u]=v;
}
int main()
{
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,k,i,j;
long long ans=0;
cin>>n>>m>>k;
for(i=1;i<=n;i++)
fa[i]=i;
for(i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
e[i].u=u,e[i].v=v,e[i].w=w;
}
for(i=1;i<=k;i++)
{
cin>>c[i];
for(j=1;j<=n;j++)
cin>>a[j];
}
sort(e+1,e+m+1,cmp);
int cnt=n-1;
for(i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v;
if(fid(u)!=fid(v))//It was fid[u] here,haha.
{
ans+=e[i].w;
merge(u,v);
if(!(--cnt))
break;
}
}//Kruskal
cout<<ans<<'\n';
return 0;
}
//Near to AC,but this might not be so easy,meow.
::::
T3
看到题目后确实想到过 KMP,但没想到怎么去用。看了一眼特殊性质 B 就直接开写了,对于每组
时间复杂度
接着开始写暴力,写的时候把
::::info[题面]
题目描述
小 W 是一名喜欢语言学的算法竞赛选手。在语言学中,谐音替换是指将原有的字词替换为读音相同或相近的字词。小 W 发现,谐音替换的过程可以用字符串来进行描述。具体地,小 W 将谐音替换定义为以下字符串问题:
给定
对于字符串
- 对于
s 的某个子串y ,若存在1 \leq i \leq n 满足y = s_{i,1} ,则将y 替换为y' = s_{i,2} 。具体地,设s = x + y + z ,其中x 和z 可以为空,“+” 表示字符串拼接,则s 的替换将得到字符串s' = x + y' + z 。
小 W 提出了
输入格式
输入的第一行包含两个正整数
输入的第
输入的第
输出格式
输出
输入输出样例 #1
输入 #1
4 2
xabcx xadex
ab cd
bc de
aa bb
xabcx xadex
aaaa bbbb
输出 #1
2
0
输入输出样例 #2
输入 #2
3 4
a b
b c
c d
aa bb
aa b
a c
b a
输出 #2
0
0
0
0
说明/提示
【样例 1 解释】
对于小 W 的第一个询问,共有
- 令
x, z 均为空串,y = \text{xabcx} ,i = 1 ,则y' = \texttt{xadex} ,替换后得到\text{xadex} ; - 令
x = \texttt{xa} ,y = \texttt{bc} ,z = \texttt{x} ,i = 3 ,则y' = \texttt{de} ,替换后得到\texttt{xadex} 。
【样例 3】
见选手目录下的
该样例满足测试点 11, 12 的约束条件。
【样例 4】
见选手目录下的
该样例满足测试点 15, 16 的约束条件。
【数据范围】
设
-
-
- 对于所有
1 \leq i \leq n ,s_{i,1}, s_{i,2} 均仅包含小写英文字母,且|s_{i,1}| = |s_{i,2}| ; - 对于所有
1 \leq j \leq q ,t_{j,1}, t_{j,2} 均仅包含小写英文字母,且t_{j,1} \neq t_{j,2} 。
::cute-table{tuack}
| 测试点编号 | 特殊性质 | ||
|---|---|---|---|
| 无 | |||
| ^ | |||
| ^ | AB | ||
| ^ | A | ||
| ^ | B | ||
| ^ | 无 | ||
| ^ | A | ||
| ^ | ^ | B | |
| ^ | ^ | 无 |
特殊性质 A:
特殊性质 B:定义字符串
::::info[Code(15pts)]
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int l,mid,r;
};
vector<Node> tt;
bool check(string s1,string s2,string s3)
{
int l=s1.size();
for(int i=0;i<l;i++)
{
if(!((s1[i]=='$'&&s1[i]==s3[i])||s1[i]==s2[i]))
return false;
}
return true;
}
int fid(string s1,string s2)
{
int l=s1.size();
int i,j;
for(i=0,j=s2.size()-1;j<l;i++,j++)
{
bool flag=true;
int x;
for(int k=i;k<=j;k++)
{
if(s2[k-i]!=s1[k])
{
flag=false;
break;
}
}
if(flag)
return i;
}
return -1;
}
void repla(string &s,int p,string s1)
{
for(int i=p;i<p+s1.size();i++)
{
s[i]=s1[i-p];
}
}
int main()
{
freopen("replace.in","r",stdin);
freopen("replace.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
string s1,s2;
int n,q,i,j;
cin>>n>>q;
if(n<=100&&q<=100)
{
string t1[105],t2[105];
for(i=1;i<=n;i++)
cin>>t1[i]>>t2[i];
while(q--)
{
cin>>s1>>s2;
int l1=s1.size(),l2=s2.size();
int ans=0;
if(l1!=l2)
{
cout<<0<<'\n';
continue;
}
for(i=1;i<=n;i++)
{
string ab=s1;
while(fid(ab,t1[i])!=-1)
{
string sbc=ab;
repla(ab,fid(ab,t1[i]),t2[i]);
if(check(ab,s2,s1))
{
ans++;
break;
}
else
{
ab=sbc;
ab[fid(ab,t1[i])]='$';
}
}
}
cout<<ans<<'\n';
}
return 0;
}
for(i=1;i<=n;i++)
{
cin>>s1>>s2;
int l1=s1.size(),l2=s2.size(),ll1,rr1,ll2,rr2,xx1,xx2,dl,dr,dm;
for(j=0;j<l1;j++)
{
if(s1[j]=='b')
{
ll1=j;
rr1=l1-j-1;
xx1=j;
}
}
for(j=0;j<l2;j++)
{
if(s2[j]=='b')
{
ll2=j;
rr2=l2-j-1;
xx2=j;
}
}
if(xx1<xx2)
dl=ll1,dr=rr2,dm=xx2-xx1;
else
dl=ll2,dr=rr1,dm=xx2-xx1;
tt.push_back({dl,dm,dr});
}
int pp=tt.size();
for(i=1;i<=q;i++)
{
cin>>s1>>s2;
int ans=0;
int l1=s1.size(),l2=s2.size();
if(l1!=l2)
{
cout<<0<<'\n';
continue;
}
int ll1,rr1,ll2,rr2,xx1,xx2,dl,dm,dr;
for(j=0;j<l1;j++)
{
if(s1[j]=='b')
{
ll1=j;
rr1=l1-j-1;
xx1=j;
}
}
for(j=0;j<l2;j++)
{
if(s2[j]=='b')
{
ll2=j;
rr2=l2-j-1;
xx2=j;
}
}
if(xx1<xx2)
dl=ll1,dr=rr2,dm=xx2-xx1;
else
dl=ll2,dr=rr1,dm=xx2-xx1;
for(j=0;j<pp;j++)
{
if(dm==tt[j].mid&&dl>=tt[j].l&&dr>=tt[j].r)
ans++;
}
cout<<ans<<'\n';
}
return 0;
}//Meow.Bad.
::::
T4
输出随机数。给 4pts 吧球球了。
::::info[题面]
题目描述
小 Z 和小 H 想要合伙开一家公司,共有
小 H 是面试官,将在接下来
小 H 准备了
然而,每个人的耐心都有一定的上限,如果在他面试之前未录用的人数过多,则他会直接放弃参加面试。具体地,编号为
小 Z 想知道一共有多少种面试的顺序
输入格式
输入的第一行包含两个正整数
输入的第二行包含一个长度为
输入的第三行包含
输出格式
输出一行一个非负整数,表示能够录用至少
输入输出样例 #1
输入 #1
3 2
101
1 1 2
输出 #1
2
输入输出样例 #2
输入 #2
10 5
1101111011
6 0 4 2 1 2 5 4 3 3
输出 #2
2204128
说明/提示
【样例 1 解释】
共有以下 2 种面试的顺序
【样例 3】
见选手目录下的
该样例满足测试点 6 ~ 8 的约束条件。
【样例 4】
见选手目录下的
该样例满足测试点 12 ~ 14 的约束条件。
【样例 5】
见选手目录下的
该样例满足测试点 18 ~ 21 的约束条件。
【数据范围】
对于所有测试数据,保证:
-
- 对于所有
1 \leq i \leq n ,均有s_i \in \{0,1\} ; - 对于所有
1 \leq i \leq n ,均有0 \leq c_i \leq n 。
::cute-table{tuack}
| 测试点编号 | 特殊性质 | ||
|---|---|---|---|
| 无 | |||
| ^ | ^ | ||
| ^ | A | ||
| ^ | ^ | 无 | |
| ^ | |||
| ^ | ^ | ||
| ^ | A | ||
| ^ | ^ | B | |
| ^ | ^ | 无 |
特殊性质 A: 对于所有
特殊性质 B: 在
::::info[Code(0pts 喵)]
#include<bits/stdc++.h>
using namespace std;
int main()
{
freopen("employ.in","r",stdin);
freopen("employ.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
srand(time(NULL));
cout<<rand()<<endl;
return 0;
}//Meow.4pts,please.
::::
赛后
出考场后听说很多童鞋 T1 没做出来,还有一些心态直接爆炸了(bjx 甚至没做 T3 和 T4 啊)。5 个同学一起吃了 KFC,只花了 89 就做到了每人一个汉堡、一杯饮料和一份鸡腿/鸡翅还有共享的一份鸡米花。真的太有性价比了。这不比黄焖鸡爽喵。
给同学打了把王者,超鬼了(
车上又看了会儿黑盒,玩了会儿游戏。bjx 睡醒后在玩 mc,居然还是生存大佬啊喵。22:00 到学校了,懒得拿东西直接回家了。
总结
如果 T1 没挂的话还是挺满意的,应该是第一次场切绿题(现在降黄了)。能进 NOIP 就行,几等奖已经无所谓了。和 bjx 贴贴开心喵。
其实 T2 写个暴力就一等了。
最终分数: