[题解]ABC346 C~E
想起上次的ABC346没打,刚才虚拟参赛打了A~D,E题思路有,但是实现方式没选好导致WA了,没能在赛时做出来。写下题解记录一下~
C - Σ
用求和公式先把\(1\sim k\)的和求出来:\(\frac{k(k+1)}{2}\),然后对于\(A\)数组中的元素依次减去就行(注意相同元素不能减\(2\)次)
点击查看代码
#include<bits/stdc++.h> #define int long long using namespace std; int n,k,a[200010]; unordered_map<int,bool> m; signed main(){ cin>>n>>k; int ans=(k+1)*k/2; for(int i=1;i<=n;i++){ cin>>a[i]; if(!m[a[i]]){ m[a[i]]=1; if(a[i]<=k) ans-=a[i]; } } cout<<ans; return 0; }
D - Gomamayo Sequence
这个题就是让我们把字符串变成一个01交替,但是中间有且仅有一个00或者11的字符串。
所以我们可以枚举在哪里重复,需要注意的是一个位置有两种情况,比如:
1010101001010
0101010110101
从重复的位置分割,可以形成0101+1010
或1010+0101
结构的字符串,这样我们只需要知道前缀和后缀需要多少次变化成0101
或1010
就行。可以通过预处理来维护前缀的代价和后缀的代价,各需要两个数组,分别维护变成\(0101…\)和\(1010…\)的代价。这样\(O(n)\)枚举,\(O(1)\)查询,总时间复杂度\(O(n)\)。
点击查看代码
#include<bits/stdc++.h> #define int long long using namespace std; int n,c[200010]; int f[4][200010]; //0:0101...前缀 1:1010...前缀 //2:0101...后缀 3:1010...后缀 string s; signed main(){ cin>>n>>s; s=' '+s; for(int i=1;i<=n;i++){ cin>>c[i]; } for(int i=1;i<=n;i++){ char temp='0'+i%2,ltemp='0'+(n-i+1)%2; f[0][i]=f[0][i-1]+(s[i]==temp)*c[i]; f[1][i]=f[1][i-1]+(s[i]!=temp)*c[i]; f[2][n-i+1]=f[2][n-i+2]+(s[n-i+1]==ltemp)*c[n-i+1]; f[3][n-i+1]=f[3][n-i+2]+(s[n-i+1]!=ltemp)*c[n-i+1]; } int ans=LLONG_MAX; for(int i=2;i<=n;i++){ ans=min(ans,f[0][i-1]+f[3][i]); ans=min(ans,f[1][i-1]+f[2][i]); } cout<<ans; return 0; }
E - Paint
首先我们对原数组进行一个去重,也就是\(t\)和\(a\)都相同的操作,以最后面的为准。这样每行每列都最多有\(1\)次操作。
倒序遍历,记录下填充了多少行,多少列,每次累加需要减去,比如当前填充某一行,此后填充了\(cntv\)列,那么这个颜色实际上只填了\(w-cntv\)个格子,列同理。
用\(vis\)数组+倒序遍历可以省掉去重这一步骤。
点击查看代码
#include<bits/stdc++.h> #define int long long using namespace std; int h,w,m; int t[200010],a[200010],x[200010]; bool vx[200010],vy[200010]; int ans[200010]; //0=op1 1=op2 signed main(){ cin>>h>>w>>m; for(int i=1;i<=m;i++) cin>>t[i]>>a[i]>>x[i]; int cnth=0,cntv=0;//多少行和多少列涂了颜色 for(int i=m;i>=1;i--){ if(t[i]==1&&!vx[a[i]]){//涂的行 vx[a[i]]=1; ans[x[i]]+=w-cntv; cnth++; } if(t[i]==2&&!vy[a[i]]){//涂的列 vy[a[i]]=1; ans[x[i]]+=h-cnth; cntv++; } } int cntans=0; ans[0]=h*w; for(int i=1;i<=200000;i++) ans[0]-=ans[i]; for(int i=0;i<=200000;i++) cntans+=bool(ans[i]); cout<<cntans<<endl; for(int i=0;i<=200000;i++){ if(ans[i]){ cout<<i<<" "<<ans[i]<<endl; } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效