[题解]CSP-S 2025 T1~T3 题解

news/2025/11/2 21:47:22/文章来源:https://www.cnblogs.com/Sinktank/p/19184544

T1. P14361 [CSP-S 2025] 社团招新 / club

Tag:贪心、排序。

因为要求每个社团不超过 \(\dfrac{n}{2}\) 个人,所以无论怎么分配,最多只会有一个社团超出限制。

因此,我们先让每个人选最满意的社团。若存在超出限制的社团,则从中调出一些人,使其恰好剩余 \(\dfrac{n}{2}\) 个人。此时一定没有社团超出限制。

为了让答案尽可能优,调出的人的最大满意度 \(-\) 次大满意度应尽可能小。

时间复杂度 \(O(n\log n)\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define eb emplace_back
using namespace std;
const int N=1e5+5,inf=1e15;
int t,n,a[5],c[5];
vector<int> v[5];
signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>t;c[0]=-inf;while(t--){v[1].clear(),v[2].clear(),v[3].clear();cin>>n;int ans=0;for(int i=1;i<=n;i++){int mxp=0,_mxp=0;for(int j=1;j<=3;j++){cin>>a[j];if(a[j]>=a[mxp]) _mxp=mxp,mxp=j;else if(a[j]>a[_mxp]) _mxp=j;}ans+=a[mxp];v[mxp].eb(a[mxp]-a[_mxp]);}for(int i=1;i<=3;i++){if((int)v[i].size()>n/2){sort(v[i].begin(),v[i].end());for(int j=0;j<(int)v[i].size()-n/2;j++) ans-=v[i][j];}}cout<<ans<<"\n";}return 0;
}

T2. P14362 [CSP-S 2025] 道路修复 / road

Tag:图论、生成树。

我们可以直接 \(O(2^k)\) 地枚举对哪些乡村进行改造,然后将它们与城市的边连上,跑 MST。时间复杂度 \(O(2^k m(\log m+\alpha(n)))\),期望得分 \(60\text{ pts}\)

排序可以在枚举前进行,而且城市之间的连边可以只保留 MST 上的。时间复杂度 \(O(m\log m+(nk)\log(nk)+2^k(nk+\alpha(n)))\)

进一步考虑,额外改造一个乡村后的 MST,只可能包含原 MST 和新加的 \(n\) 条边。可以通过归并在 \(O((n+k)\alpha(n))\) 内求得。时间复杂度 \(O(2^k(n+k)\alpha(n))\)

洛谷上的民间数据,后两种做法都能通过。

#1 - 8.27s
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int M=1e6+2,N=1e4+2,K=12,inf=1e18;
int n,m,k,fa[N+K],idx,c[K],ans=inf;
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
struct Ed{int u,v,w;}_e[M],e[N+N*K];
inline bool cmp(Ed a,Ed b){return a.w<b.w;}
bitset<K> vis;
signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m>>k;for(int i=1,u,v,w;i<=m;i++){cin>>u>>v>>w;_e[i]={u,v,w};}sort(_e+1,_e+1+m,cmp);for(int i=1;i<=n;i++) fa[i]=i;for(int i=1;i<=m;i++){int u=find(_e[i].u),v=find(_e[i].v);if(u^v) fa[u]=v,e[++idx]=_e[i];}for(int i=1,x;i<=k;i++){cin>>c[i];for(int j=1;j<=n;j++){cin>>x;e[++idx]={n+i,j,x};}}sort(e+1,e+1+idx,cmp);for(int sta=(1<<k)-1;~sta;sta--){int s=0;for(int i=1;i<=k;i++){if((sta>>(i-1))&1) vis[i]=1,s+=c[i];else vis[i]=0;}for(int i=1;i<=n+k;i++) fa[i]=i;for(int i=1;i<=idx;i++){int u=e[i].u,v=e[i].v,w=e[i].w;if(u>n&&!vis[u-n]) continue;u=find(u),v=find(v);if(u^v) fa[u]=v,s+=w;}ans=min(ans,s);}cout<<ans<<"\n";return 0;
}
#2 - 5.96s
#include<bits/stdc++.h>
#define int long long
#define eb emplace_back
using namespace std;
const int M=1e6+2,N=1e4+2,K=11,inf=1e18;
int n,m,k,fa[N+K],c[K],ans=inf;
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
struct Ed{int u,v,w;};
vector<Ed> _e,a[K],e[K];
inline bool cmp(Ed a,Ed b){return a.w<b.w;}
inline int merge(vector<Ed>& a,vector<Ed>& b,vector<Ed>& res){auto it=b.begin();_e.clear(),res.clear();int s=0;for(int i=1;i<=n+k;i++) fa[i]=i;for(Ed i:a){for(;it!=b.end()&&it->w<=i.w;it++) _e.eb(*it);_e.eb(i);}for(;it!=b.end();it++) _e.eb(*it);for(Ed i:_e){int u=find(i.u),v=find(i.v);if(u^v) fa[u]=v,res.eb(i),s+=i.w;}return s;
}
inline void dfs(int p,int s,int sc){//s为修复边的花费,sc为改造的花费if(p>k){return ans=min(ans,s+sc),void();}e[p]=e[p-1],dfs(p+1,s,sc);//不改造dfs(p+1,merge(e[p-1],a[p],e[p]),sc+c[p]);//改造
}
signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m>>k;for(int i=1,u,v,w;i<=m;i++){cin>>u>>v>>w;_e.eb(Ed{u,v,w});}sort(_e.begin(),_e.end(),cmp);for(int i=1;i<=n;i++) fa[i]=i;int s=0;for(Ed i:_e){int u=find(i.u),v=find(i.v);if(u^v) fa[u]=v,e[0].eb(i),s+=i.w;}for(int i=1,x;i<=k;i++){cin>>c[i];for(int j=1;j<=n;j++){cin>>x;a[i].eb(Ed{n+i,j,x});}sort(a[i].begin(),a[i].end(),cmp);}dfs(1,s,0);cout<<ans<<"\n";return 0;
}

T3. P14363 [CSP-S 2025] 谐音替换 / replace

Tag:字符串、Trie 树、数据结构。

我们可以直接对询问串进行字符串哈希,然后逐位枚举。时间是 \(O(L_1+nL_2)\),期望得分 \(25\text{ pts}\)

特殊性质 B 蛮有启发性的。由于所有串串都由 ab 构成,且 b 恰出现一次,所以所有模式串对 / 询问串对都可以用一个点对 \((x,y,p)\) 来描述。

其中,\(x,y\) 分别表示前串中 b 从左往右数、从右往左数的位置;\(p\) 表示前串到后串 b 位置的变化量。

那么模式串 \((x',y',p')\) 能对询问 \((x,y,p)\) 产生贡献,当且仅当:

  • \(x'\le x\)
  • \(y'\le y\)
  • \(p'=p\)

我们按 \(p\) 分组,每一组内做二维数点即可。时间复杂度 \(O(L_1+L_2+(n+q)\log L_1)\)


接下来考虑一般情况。

对于模式串对 \(s=(s_1,s_2)\),我们可以找到它们第一个和最后一个不同的位置,构成一个极小替换区间 \([l,r]\),记区间内的内容为 \(s_1',s_2'\)

那么 \(s\) 可以表示为 \((l+s_1'+r,l+s_2'+r)\)

同理 \(t\) 可以表示为 \((L+t_1'+R,L+t_2'+R)\)

则模式串对 \((s_1',s_2')\) 能对询问串对 \((t_1',t_2')\) 产生贡献,当且仅当:

  • \(l\)\(L\) 的后缀。
  • \(r\)\(R\) 的前缀。
  • \((s_1',s_2')=(t_1',t_2')\)

对于第三条,我们按哈希值(或用 Trie 树)分组即可。

第一、二条描述的前后缀关系,放在 Trie 树上就是祖先和后代的关系。按 DFS 序编号后,同样可以转化为二维数点求解。时间复杂度 \(O(L_1|\Sigma|+L_2+(n+q)\log(n+q))\)

这里也可以用 AC 自动机来做:对所有 \(\overline{l\texttt{\#}s_1's_2'\texttt{\#}r}\) 建立 AC 自动机,询问串同样写成 \(\overline{l\texttt{\#}t_1't_2'\texttt{\#}r}\),在上面跑多模式匹配即可。时间复杂度应该是 \(O(L_1|\Sigma|+L_2)\)。但是我不会写(逃

注意先把 \(|t_1|\ne|t_2|\) 判掉。

Ref:代码参照 by 20_200

点击查看代码
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#define fi first
#define se second
using namespace std;
using namespace __gnu_pbds;
typedef unsigned long long ull;
const int N=2e5+5,Q=2e5+5,L1=5e6+5,C=26,B=233;
gp_hash_table<ull,int> to;
int n,q,tn,rt[N<<1],idx,ans[Q];
pair<int,int> tmp[N];
inline ull hs(string &s){ull a=0;for(char i:s) a=a*B+i;return a;
}
struct TRIE{int f[L1][C],dfn[L1],dfm[L1],idx,tim;inline int ins(int x,string &s){for(char i:s){if(!f[x][i-'a']) f[x][i-'a']=++idx;x=f[x][i-'a'];}return x;}inline void dfs(int x){dfn[x]=++tim;for(int i=0;i<C;i++) if(f[x][i]) dfs(f[x][i]);dfm[x]=tim;}inline int qry(int x,string &s){for(char i:s){if(f[x][i-'a']) x=f[x][i-'a'];else return x;}return x;}
}tr;
inline int lb(int x){return x&-x;}
struct BIT{int s[L1];inline void chp(int x,int v){for(;x<=tr.idx;x+=lb(x)) s[x]+=v;}inline int qry(int x){int a=0;for(;x;x-=lb(x)) a+=s[x];return a;}
}bit;
struct Point{int x,y,k;bool t;}pt[4*N+Q];
signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>q;string s1,s2,sl,sr,s;for(int i=1;i<=n;i++){cin>>s1>>s2,sl=sr=s="";int m=s1.size(),l=0,r=m-1;while(l<m&&s1[l]==s2[l]) sl+=s1[l++];while(r>l&&s1[r]==s2[r]) sr+=s2[r--];reverse(sl.begin(),sl.end());reverse(sr.begin(),sr.end());for(int j=l;j<=r;j++) s+=s1[j],s+=s2[j];ull h=hs(s);int &x=to[h];if(!x) rt[x=++tn]=++tr.idx,rt[++tn]=++tr.idx;tmp[i]={tr.ins(rt[x],sl),tr.ins(rt[x+1],sr)};}for(int i=1;i<=tn;i++) tr.dfs(rt[i]);for(int i=1;i<=n;i++){pt[++idx]={tr.dfn[tmp[i].fi],tr.dfn[tmp[i].se],1,0};pt[++idx]={tr.dfn[tmp[i].fi],tr.dfm[tmp[i].se]+1,-1,0};pt[++idx]={tr.dfm[tmp[i].fi]+1,tr.dfn[tmp[i].se],-1,0};pt[++idx]={tr.dfm[tmp[i].fi]+1,tr.dfm[tmp[i].se]+1,1,0};}for(int i=1;i<=q;i++){cin>>s1>>s2,sl=sr=s="";if(s1.size()!=s2.size()) continue;int m=s1.size(),l=0,r=m-1;while(l<m&&s1[l]==s2[l]) sl+=s1[l++];while(r>l&&s1[r]==s2[r]) sr+=s2[r--];reverse(sl.begin(),sl.end());reverse(sr.begin(),sr.end());for(int j=l;j<=r;j++) s+=s1[j],s+=s2[j];ull h=hs(s);if(to.find(h)==to.end()) continue;int x=to[h];pt[++idx]={tr.dfn[tr.qry(rt[x],sl)],tr.dfn[tr.qry(rt[x+1],sr)],i,1};}sort(pt+1,pt+1+idx,[](Point a,Point b){return a.x==b.x?a.t<b.t:a.x<b.x;});for(int i=1;i<=idx;i++){if(pt[i].t) ans[pt[i].k]=bit.qry(pt[i].y);else bit.chp(pt[i].y,pt[i].k);}for(int i=1;i<=q;i++) cout<<ans[i]<<"\n";return 0;
}

T4. P14364 [CSP-S 2025] 员工招聘 / employ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/953823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于git关联github问题

本地GIT绑定GITHUB 配置本地GIT信息 #配置用户名 git config --global user.name "test"#配置邮箱 git config --global user.email abc@163.com生成本地密钥和公钥 生成ssh文件夹(生成ssh秘钥)(输入$ s…

AT ABC285E Work or Rest 题解

SolutionLink 有趣的 DP 题,难点在于从哪里开始入手以及优化(也许)。 显然 DP 可以方便地处理这个 \(\max\) 值的转移,但是从哪个位置开始 DP 呢?注意到周期呈现环状,也就是说一周的第 \(n\) 天和下一周的第 \(1…

代码复杂度的代价远比你想象得大

引言:复杂度的代价远比你想象得大 在 Java 后端系统演进过程中,代码复杂度是影响可维护性、稳定性和迭代效率的核心因素。然而,复杂度往往被忽视,直到一次“小改动”引发线上事故,才被重新审视。 本文以“复杂度战…

CSP2025 - S 年度总结大会报告

各大 oj 估分:洛谷:\(100+52+10+8=170\)。 小图灵:\(100+60+?+8=168+?\),当时他 \(T_3\) 数据还没有造。 梦熊:\(100+92+30+8=230\),感觉不准。自己估分:\(100+[48,70]+[0,40]+8=[156,218]\)。 第一:明确自己…

25CSP退役游记(11.1更新)

关于我在考虑要不要把S1的P话也加进来这件事 day—— -5 今天天气晴朗,不很像秋天,更不像济南今年的秋天。 考前焦虑期也是要休息的。它从一周之前来,从三四天之后来,这么算三个周能休七八天,比我的假期多多了。但…

第二章实践作业

第二章实践作业分治法找第 k 小的数:基础理解与思考 一、用分治法找第 k 小的数 找第 k 小的数,用分治法来解决其实思路还挺直观的。大概可以分成这几步: 先选一个 “基准数”,随便从数组里挑一个就行,比如选第一…

(补11月)代码大全阅读笔记2

第6-9章的架构设计内容,彻底解答了我长期以来的核心困惑:为何同样实现了基础功能的代码,有的在后续迭代中能轻松响应需求变化,有的却如同“牵一发而动全身”的乱麻,修改一个小功能就引发连锁bug。书中系统阐述的“…

java 基础语法一

java 基础语法一 一、基本概念 冯诺依曼结构,Java三大版本、编译型和解释型语言 1、五大组成部分:运算器、控制器、存储器、输入设备和输出设备;核心特点:采用二进制表示、存储程序原理、顺序执行指令 2、javaSE(…

VisualStudio 2022如何打开.slnx文件格式的解决方案

打开VisualStudio 2022,菜单中设置-选项-环境 > 预览功能 > 勾选最下方的“使用解决方案文件持久性模型”设置,再手动对.slnx文件进行关联设置即可。

(补11月)代码大全阅读笔记3

研读第23-25章关于测试与调试的内容后,我彻底摒弃了“开发负责写代码,测试负责找bug”的错误认知,建立起“开发者是质量第一责任人”的核心意识。书中一组数据让我尤为震撼:单元测试阶段发现并修复bug的成本,仅为…

CSP2025 - S 游记

Day -14 那天的模拟赛考得不错,拿了全校第二。 Day -13 太阳神开家长会骂了我们竞赛生。 心情不爽。 Day -11 晚上上厕所偶遇 xz,xz说我状态不错继续保持。 心情大好。 Day -7 集训,但是状态明显降低。 Day -5 没有…

CSP-S游记

CSP-S游记 首先读题,T1感觉直接贪心即可,T2应该不难,T3没想法,T4是计数我比较喜欢。 T1很快想出来代码也很好写20分钟过掉。 T2很容易想到 \(O(2^kn\log n)\) 的做法,但不确定能不能过就想优化把log去掉,想了一个…

小组作业1

小组作业1这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/homework/13471姓名 学…

C语言字符串及其函数

字符串及其函数c语言 没有字符串类型,所以大多用字符数组代替。 1. 字符串的输入输出 使用 scanf 和 printf 的通用输入输出。 #include <stdio.h> #include <stdlib.h>/* run this program using the co…

CPULOAD建模设计

背景: 1.中断周期的建模 在单片机中中断和任务是两类处理数据的主要形式,中断的形式主要分为周期和时间两类。比如,LIN中断是根据调度表的周期去响应的,滚轮这种则是根据外部事件响应的。 2.响应时间的建模 中断的…

C 文件操作全解速览

文件操作文件分为二进制文件和文本文件,文本文件里面保存的内容形式是ASCII字符,二进制文件里面内容保存形式是01表示的。文件的主要作用是用来进行数据的持久化,能去长久的保存数据。这里f开头的文件操作命令,大多…

Java记录类:简化数据载体的新选择

Java 14引入的record类型为开发者提供了一种声明数据载体的简洁方式,有效减少了样板代码的编写。记录类旨在透明地保存不可变数据,自动实现数据访问方法和对象常用方法。 基本语法非常简单: public record User(Str…

第二次算法作业

基本思路 该算法采用分治策略来寻找数组中第k小的元素。首先从数组中随机选择一个基准元素,然后将数组划分为三个部分:小于基准的元素、等于基准的元素和大于基准的元素。根据k值所在的范围,决定在哪个子数组中继续…

NOIP 2025 游记 退役记

【洛谷专栏】 前言 前作:NOIP 2024 游记。 上一篇文章:CSP-S 2025 游记(The Last CSP ver.)。 同样地支持友链互挂,请私信。 CSP 结束了,可能没有冬令营机会了。 联赛,翻盘,还是,很难。 正文 2025.11 11.1 提…

一个万古常青的、小而美的输入法

一个万古常青的、小而美的输入法万古常青apt install fcitx-sunpinyin 即可安装。Ubuntu和Debian不倒,就一直有。美系统词库为libgooglepinyin和sunpinyin的合并去重版,词比它们都多。 用sunpinyin训练了字的三元语法…