CSP-S 2024 题解

embedded/2024/12/29 5:57:59/

前言:所给代码只过了民间数据,可能与实际成绩略有出入。

T1:决斗

为了让退出游戏的怪兽数量尽可能多,肯定是 r r r 大的打 r r r 小的,所以考虑用桶维护 r r r 的出现次数,对于一个新的 r r r 值,先让它打败 r r r 比它小的,然后再加上它的数量。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,cnt[N],ans;
int main(){cin>>n;for(int i=1;i<=n;i++){int x;cin>>x;cnt[x]++;}for(int i=1;i<=1e5;i++){ans-=min(ans,cnt[i]);ans+=cnt[i];}cout<<ans<<endl;return 0;
}

T2:超速检测

对于不同的加速度分类讨论,不难发现所有车超速的范围都是一个区间。

进而所有车能被测速仪测到的范围也是一个区间,这个可以通过二分预处理出来。

然后问题变为给我们若干个区间,选最少的点使得每个区间都至少覆盖到一个选中的点,这是个经典的贪心问题。

首先先按 l l l 从小到大排序, l l l 相等的按 r r r 从大到小排序。对于 [ l i , r i ] , [ l j , r j ] [l_i,r_i],[l_j,r_j] [li,ri],[lj,rj],若 i i i 区间完全包含 j j j 区间,则 i i i 区间无用,然后我们就保证剩下的区间都按 l , r l,r l,r 从小到大排序,接下来就很容易做了。

#include<bits/stdc++.h>
using namespace std;
#define rd read()
#define double long double
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define ROF(i,j,k) for(int i=j;i>=k;i--)
const int N=1e5+10,INF=1e9;
int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;
}
int T,n,m,p[N],d[N],a[N],V,L,v[N],tot,res,del[N];
struct node{int l,r;}seg[N];
bool cmp(node a,node b){if(a.l!=b.l) return a.l<b.l;return a.r>b.r;
}
int main(){T=rd;while(T--){tot=res=0,n=rd,m=rd,L=rd,V=rd;FOR(i,1,n) d[i]=rd,v[i]=rd,a[i]=rd;FOR(i,1,m) p[i]=rd;sort(p+1,p+1+m);FOR(i,1,n){if(a[i]<=0&&v[i]<=V) continue;if(a[i]>0){int dis=V*V-v[i]*v[i];dis/=2*a[i],dis+=d[i];if(v[i]>V) dis=d[i]-1; int pos=0,l=1,r=m;while(l<=r){int mid=(l+r)>>1;if(p[mid]>dis) pos=mid,r=mid-1;else l=mid+1;}if(!pos) continue;seg[++tot]={pos,m};}else{int l=1,r=m,posl=0,posr=0;while(l<=r){int mid=(l+r)>>1;if(p[mid]>=d[i]) posl=mid,r=mid-1;else l=mid+1;}if(!posl) continue;l=posl,r=m;while(l<=r){int mid=(l+r)>>1;double tmp=sqrt(1.0*v[i]*v[i]+2.0*a[i]*(p[mid]-d[i]));if(tmp>V) l=mid+1,posr=mid;else r=mid-1;}if(posr<posl) continue;seg[++tot]={posl,posr};}}sort(seg+1,seg+1+tot,cmp),memset(del,0,sizeof(del));int mnr=INF;ROF(i,tot,1){if(mnr<=seg[i].r) del[i]=1;mnr=min(mnr,seg[i].r);}mnr=0;FOR(i,1,tot){if(del[i]) continue;if(mnr<seg[i].l){res++,mnr=seg[i].r;}}printf("%d %d\n",tot,m-res);}return 0;
}

T3:染色

一眼 dp 题。

f i , 0 / 1 f_{i,0/1} fi,0/1 表示前 i i i 个数,第 i i i 个数染蓝 / 红色所能得到的最大价值,答案为 max ⁡ ( f n , 0 , f n , 1 ) \max(f_{n,0},f_{n,1}) max(fn,0,fn,1)

考虑怎么转移,不难发现对于 i i i,它可以不产生贡献,直接从 max ⁡ ( f i − 1 , 0 , f i − 1 , 1 ) \max(f_{i-1,0},f_{i-1,1}) max(fi1,0,fi1,1) 转移过来。

再考虑它要与之前的一个与它相等的位置配对,显然肯定要与它的前驱配对,这样才是最优的。而每个位置的前驱可以 O ( n ) O(n) O(n) 预处理。

i i i 的前驱为 l l l [ l + 1 , i − 1 ] [l+1,i-1] [l+1,i1] 区间内的数一定会染同色。我们思考如何得到贡献,发现可以由三部分组成,首先是 f l + 1 , c o l i ⊕ 1 f_{l+1,col_i\oplus 1} fl+1,coli1,再就是 [ l + 2 , i − 1 ] [l+2,i-1] [l+2,i1] 区间全染同色可以产生的贡献,然后是 a i a_i ai。最后取一遍 max ⁡ \max max 即可。

注意特判 l = i − 1 l=i-1 l=i1 的情况,此时转移为 f i , c o l i = f i − 1 , c o l i + a i f_{i,col_i}=f_{i-1,col_i}+a_i fi,coli=fi1,coli+ai

实际上 f i , 0 / 1 f_{i,0/1} fi,0/1 是可以改为 f i f_i fi 的,从转移式即可看出。

#include<bits/stdc++.h>
using namespace std;
#define rd read()
#define ll long long
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define ROF(i,j,k) for(int i=j;i<=k;i--)
const int N=2e5+10,M=1e6+10;
int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;
}
int n,pos[M],la[N],a[N],T;ll s[N],f[N][2];
int main(){T=rd;while(T--){memset(pos,0,sizeof(pos)),memset(la,0,sizeof(la)),memset(f,0,sizeof(f)),memset(s,0,sizeof(s));n=rd;FOR(i,1,n){a[i]=rd;la[i]=pos[a[i]],pos[a[i]]=i;}FOR(i,1,n) s[i]=s[i-1]+(a[i]==a[i-1])*a[i];FOR(i,1,n){int l=la[i];ll res1=0,res2=0;f[i][0]=f[i][1]=max(f[i-1][0],f[i-1][1]);if(l!=i-1&&l>0){res1=f[l+1][1]+a[i]+s[i-1]-s[l+1];res2=f[l+1][0]+a[i]+s[i-1]-s[l+1];}else if(l==i-1&&l>0) res1=f[i-1][0]+a[i],res2=f[i-1][1]+a[i];f[i][0]=max(f[i][0],res1),f[i][1]=max(f[i][1],res2);}printf("%lld\n",max(f[n][0],f[n][1]));}return 0;
}

T4:擂台游戏

将原问题转化为判断 i i i c j c_j cj 的条件下能否成为擂主。

不难发现比赛过程会形成一颗完全二叉树,预处理出来 f x f_x fx 表示在 x x x 节点获胜的人是谁,这个可以 O ( n ) O(n) O(n) 做到。然后暴力模拟每个 i i i 向上跳的过程,根据题意分情况讨论一下,注意若有 i > n i>n i>n 的新补充的选手,他可以随意输或赢。

时间复杂度 O ( T n m l o g n ) O(Tnmlogn) O(Tnmlogn)

考虑优化,发现若前 n ′ n' n 轮时, i i i 能成为擂主,那么 n ′ ′ < n ′ n''<n' n′′<n 时, i i i 依然能成为擂主。每个 i i i 都会对 c c c 的一段区间做出贡献,设 g x g_x gx 表示跳到 x x x 节点的 n ′ n' n 的最大值,这个可以和 f f f 一起预处理出来。然后每次询问对于每个 i i i 向上跳即可。

时间复杂度 O ( T ( n l o g n + m ) ) O(T(nlogn+m)) O(T(nlogn+m))

还是不够快,思考每次询问的线性做法。

发现进行操作的区间只有 O ( n ) O(n) O(n) 个,所以从根节点开始,自顶向下不断走到左子树,对于每个左节点 dfs 一遍,会进行 ∑ i = 1 K 2 i = O ( n ) \sum_{i=1}^{K}2^i=O(n) i=1K2i=O(n)

dfs 过程中,对于从 x x x y y y 的边,倒着考虑之前 y y y x x x 的操作过程,维护两个量 v a l , m x val,mx val,mx v a l val val 反映能否跳到这次枚举的左节点, m x mx mx 反映额外的限制。

时间复杂度 O ( T ( n + m ) ) O(T(n+m)) O(T(n+m))

这道题确实古怪,具体实现细节看代码。

#include<bits/stdc++.h>
using namespace std;
#define rd read()
#define ll long long
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define ROF(i,j,k) for(int i=j;i>=k;i--)
int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;
}
const int N=4e5+10,M=20,INF=(1<<31)-1;
int n,m,T,k,a[N],aa[N],c[N],nn,X[N],p[N],t[N],f[N],g[N],op[N];ll ans[N];char s[M][N];
void dfs(int x,int d){p[d]++;if(d==k){t[x]=p[d];return;}//t[x]表示x叶子结点代表的编号op[x]=s[d][p[d]]-'0';//谁是擂主dfs(x<<1,d+1),dfs(x<<1|1,d+1);
}
void dfs1(int x,int d){//预处理f,g数组if(d==k){f[x]=t[x],g[x]=t[x]-1;return;}dfs1(x<<1,d+1),dfs1(x<<1|1,d+1);if(!op[x]){//转移比较简单if(a[f[x<<1]]>=k-d) f[x]=f[x<<1],g[x]=g[x<<1];else f[x]=f[x<<1|1],g[x]=g[x<<1|1];g[x]=max(g[x],g[x<<1]);}else{if(a[f[x<<1|1]]>=k-d) f[x]=f[x<<1|1],g[x]=g[x<<1|1];else f[x]=f[x<<1],g[x]=g[x<<1];g[x]=max(g[x],g[x<<1|1]);}
}
void update(int l,int r,int val){//差分if(l>r) return;r=min(r,nn);ans[l]+=val,ans[r+1]-=val;
}
void DFS(int x,int d,int l,int r,int val,int mx){if(l>val) return;if(d==k){int tmp=t[x];if(a[tmp]>=mx) update(max(l,tmp),min(r,val),tmp);update(l,min(tmp-1,val),tmp);return;}if(!op[x]){DFS(x<<1,d+1,l,r,val,max(mx,k-d));DFS(x<<1|1,d+1,l,r,a[f[x<<1]]>=k-d?min(val,g[x<<1]):val,mx);}else{DFS(x<<1,d+1,l,r,a[f[x<<1|1]]>=k-d?min(val,g[x<<1|1]):val,mx);DFS(x<<1|1,d+1,l,r,val,max(mx,k-d));}
}
int main(){n=rd,m=rd;FOR(i,1,n) aa[i]=rd;FOR(i,1,m) c[i]=rd;nn=1,k=0;while(nn<n) nn<<=1,k++;ROF(i,k-1,0) scanf("%s",s[i]+1);dfs(1,0);T=rd;while(T--){FOR(i,0,3) X[i]=rd;FOR(i,1,n) a[i]=aa[i]^X[i%4];FOR(i,n+1,nn) a[i]=INF;FOR(i,0,n) ans[i]=0;dfs1(1,0),update(1,1,1);int rt=1,d=0;//枚举左节点while((rt<<1)<=nn) DFS(rt,d,(1<<(k-d-1))+1,(1<<(k-d)),INF,0),rt<<=1,d++;ll res=0;FOR(i,1,n) ans[i]+=ans[i-1];FOR(i,1,m) res^=1ll*i*ans[c[i]];printf("%lld\n",res);}return 0;
}

http://www.ppmy.cn/embedded/133966.html

相关文章

(蓝桥杯C/C++)—— 编程基础

文章目录 一、C基础格式 1.打印hello, world 2.基本数据类型 二、string 1.string简介 2.string的声明和初始化 3.string其他基本操作 (1)获取字符串长度 (2) 拼接字符串( 或 append) (3&#xff09;字符串查找&#xff08;find&#xff09; (4)字符串替换 (5)提取子字符串…

优选算法精品课--双指针算法(2)

双指针算法&#xff08;2&#xff09; 1、有效三角形的个数1.1 题目解析1.2 思路解析1.3 代码实现 2、和为s的两个数2.1 题目解析2.2 思路解析2.3 代码实现 3、三数之和3.1 题目解析3.2 思路解析3.3 代码实现 4、四数之和4.1 题目解析4.2 思路解析4.3 代码实现 5 总结 1、有效三…

Mybatis使用和原理

Mybatis使用和原理 1、ORM架构2、Spring整合MyBatis使用2.1 添加maven依赖2.2 配置数据源2.3 创建实体类2.4 创建 MyBatis Mapper2.4.1 使用MyBatis注解2.4.2 使用XML方式 2.5 Service 层 3、Spring整合Hibernate使用3.1 添加maven依赖3.2 配置数据源3.3 创建实体类3.4 创建 Re…

好音质的百元头戴式耳机怎么选?四款高音质百元头戴式耳机推荐

选头戴式耳机的时候&#xff0c;品牌的选择常常让人犹豫不决。因为市面上的头戴式耳机品牌繁多&#xff0c;从知名的大牌到新兴的科技品牌&#xff0c;各种型号层出不穷&#xff0c;价格跨度也相当大。面对这些琳琅满目的选择&#xff0c;好音质的百元头戴式耳机怎么选&#xf…

爬虫+数据保存2

爬取数据保存到MySQL数据库 这篇文章, 我们来讲解如何将我们爬虫爬取到的数据, 进行保存, 而且是把数据保存到MySQL数据库的方式去保存。 目录 1.使用pymysql连接数据库并执行插入数据sql代码(insert) 2.优化pymysql数据库连接以及插入功能代码 3.爬取双色球网站的数据并保…

三种SPI机制的了解及使用

文章目录 1.SPI机制概念2.Java SPI2.1 创建一个项目&#xff0c;并创建如下模块2.2 db-api模块2.3 mysql-impl模块2.4 oracle-impl模块2.5 main-project模块 3.Spring SPI4.Dubbo SPI 1.SPI机制概念 SPI全程Service Provider Interface&#xff0c;是一种服务发现机制。 SPI的…

【网络】2.TCP通信

TCP通信 server1. 创建套接字2. 填充套接字3. 将套接字和监听文件描述符绑定4. 将_listensock设置为监听状态5. 启动服务器accept()函数read()函数 Server启动client1. 创建套接字2. 填充套接字connect()函数 3. 通过文件描述符向服务端发送信息 client启动 server server的启…

HTB:BoardLight[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many TCP ports are listening on BoardLight? 2.What is the domain name used by the box? 3.What is the name of the application running on a virtual host of board.htb? 4.What version of Dolibarr is running on Board…