Codeforces Round 982 (Div. 2) A-D个人题解
前言
本场传送门:https://codeforces.com/contest/2027
比赛只写出来了A,B 有点惭愧
A.Rectangle Arrangement
\(W=max(w_i)\)
\(H=max(h_i)\)
周长最大值\(=2\cdot(W+H)\)
B.Stalin Sort
vulnerable array性质: 最大值在最左侧
\(n\) 只有 \(2000\),可以暴力枚举,设第 \(i\) 位为这个最大值
$ [1,i-1] $ 的所有数都删掉
$ [i+1,n] $ 的数只删掉严格大于 \(a[i]\) 的
统计删掉的数的个数,求最小值
C.Add Zeros
思路
如果数组后加了 \(k\) 个0,那么 \(a_i\) 能被选上的值就是 \(n+k-i+1\)
令\(u_i=a_i-(n-i+1)\),\(u_i\) 代表的就是总共需要加多少0能选上这个数
令\(v_i=a_i-(n-i+1)+i-1\),\(v_i\) 代表的就是进入 \(u_i\) 后末尾的0总数
\(u_i\) 指向 \(v_i\) 建图(若 \(u\) 或 \(v\) 小于0则放弃这条边)
然后从0进入这张图,能到达的最大的点加上n(就是最多增加的0数)就是答案
求这个最大点我用的是记忆化dfs,开个map保存点 \(u\) 是否走过
不过貌似bfs会更好一点(?),当然也要开个map记录该点是否被走过
代码
#include<bits/stdc++.h> #define ll long long #define inf 0x3f3f3f3f3f3f3f3f using namespace std; ll n,x,ans; map<ll,vector<ll> > mp; map<ll,bool> vis; void dfs(ll x); void solve(); void dfs(ll x){ ans=max(x,ans); vis[x]=true; for(ll u:mp[x]){ if(!vis[u]){ dfs(u); } } } void solve(){ cin>>n; mp.clear(); vis.clear(); for(ll i=1;i<=n;i++){ cin>>x; ll u=x-n-1+i; ll v=x-n-1+i+i-1; if(u<0 || v<0){ continue; } vis[u]=false; vis[v]=false; mp[u].push_back(v); } ans=0; dfs(0); cout<<n+ans<<'\n'; } int main(){ ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); ll t=1; cin>>t; while(t--){ solve(); } return 0; }
D1. The Endspeaker (Easy Version)
思路
使用动态规划
\(dp[i][j]\)表示当前在 \(a_i\) 且在 \(b_j\) 的最小代价。
因为一次吸收前缀产生\(m-k\)的代价是固定的,所以尽可能在\(a\)数组里多取
最终答案就是 \(\mathop{min}\limits_{1 \leq j \leq m}( dp[n][j] )\)
对于type1 \(dp[i][j+1]=min(dp[i][j] , dp[i][j+1] )\)
对于type2 \(dp[x][j]=min(dp[i][j]+m-j , dp[x][j] )\)
其中 \(x\) 为 \(sum_x\) 满足小于等于 \(sum_i+b_j\) 最大的下标
代码
#include<bits/stdc++.h> #define ll long long #define inf 0x3f3f3f3f3f3f3f3f using namespace std; ll n,m; void solve(); void solve(){ cin>>n>>m; vector<ll> a(n+1,0),b(m+1,0),sum(n+1,0); ll Max=0; for(ll i=1;i<=n;i++){ cin>>a[i]; Max=max(Max,a[i]); sum[i]=sum[i-1]+a[i]; } for(ll i=1;i<=m;i++){ cin>>b[i]; } if(Max>b[1]){ //非法条件:a最大值比b最大值比还大 cout<<-1<<'\n'; return ; } vector<vector<ll> > dp; //直接设dp[300005][300005]会炸,所以用vector dp.resize(n+1); for(ll i=0;i<=n;i++){ dp[i].resize(m+1); } for(ll i=0;i<=m;i++){ //初始化 dp[0][i]=0LL; } for(ll i=1;i<=n;i++){ //最小值只能从i=0开始转移,所以i=0之外的都要设成inf for(ll j=0;j<=m;j++){ dp[i][j]=inf; } } for(ll i=0;i<=n;i++){ for(ll j=1;j<=m;j++){ dp[i][j]=min(dp[i][j-1],dp[i][j]); ll pos=upper_bound(sum.begin()+i,sum.end(),b[j]+sum[i])-sum.begin(); //找x就是找第一个大于b_j+sum_i的前一个下标 pos--; dp[pos][j]=min(dp[pos][j],dp[i][j]+m-j); } } ll Min=inf; for(ll i=1;i<=m;i++){ Min=min(Min,dp[n][i]); } cout<<Min<<'\n'; } int main(){ ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); ll t=1; cin>>t; while(t--){ solve(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了