Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379)题解
总体情况
A - Cyclic
题意
给你一个三位整数 N ,其中每个数字都是介于 1 和 9 之间的整数。
设 a , b , c 分别是 N 的百位、十位和个位数。打印一个按此顺序排列 b , c , a 所组成的整数,以及一个按此顺序排列 c , a , b 所组成的整数。
思路
直接模拟即可。
代码
// Problem: A - Cyclic // Contest: AtCoder - Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379) // URL: https://atcoder.jp/contests/abc379/tasks/abc379_a // Memory Limit: 1024 MB // Time Limit: 2000 ms #include<bits/stdc++.h> using namespace std; #define endl '\n' //#define int long long namespace gtx{ // Fast IO void read(int &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');} void write(char x){putchar(x);} void write(int x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(int x,char y){write(x);write(y);} #ifndef int void read(long long &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void write(long long x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(long long x,char y){write(x);write(y);} #endif signed main(){ char a,b,c; cin >> a>>b>>c; cout << b << c << a << " " << c << a << b; return 0; } } signed main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); // ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int T = 1; // gtx::read(T); while(T--) gtx::main(); return 0; }
B - Strawberries
题目大意
高桥有 N 颗牙齿,从左到右排列成一排。他牙齿目前的状况用字符串 S 表示。
如果 S 的 i 个字符是 "O",则表示左边的 i 颗牙齿是健康的。如果是 "X",则表示 i 这颗牙齿有蛀牙。健康的牙齿是没有蛀牙的。
当他有 K 颗连续健康的牙齿时,他可以用这些 K 颗牙齿吃一颗草莓。吃完一颗草莓后,这些 K 牙齿就会出现龋齿,变得不健康。
求他最多可以吃多少颗草莓。
思路
找到可以吃草莓的就赶快吃草莓即可。
代码
// Problem: B - Strawberries // Contest: AtCoder - Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379) // URL: https://atcoder.jp/contests/abc379/tasks/abc379_b // Memory Limit: 1024 MB // Time Limit: 2000 ms #include<bits/stdc++.h> using namespace std; #define endl '\n' //#define int long long namespace gtx{ // Fast IO void read(int &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');} void write(char x){putchar(x);} void write(int x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(int x,char y){write(x);write(y);} #ifndef int void read(long long &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void write(long long x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(long long x,char y){write(x);write(y);} #endif signed main(){ int n,k,ans=0; read(n);read(k); int cnt=0; for(int i = 1;i<=n;i++){ char tmp;read(tmp); if(tmp=='X') cnt=0; else{ cnt++; if(cnt==k) ans++,cnt=0; } } write(ans); return 0; } } signed main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); // ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int T = 1; // gtx::read(T); while(T--) gtx::main(); return 0; }
C - Sowing Stones
题目大意
在一行中有 N 个单元格,编号从 1 到 N 。最初, M 个单元格中包含了棋子,而 Xi 个单元格中包含了 Ai 个棋子 (1≤i≤M) 。
您可以执行以下任意次数(可能为零)的操作:
- 如果 i ( 1≤i≤N−1 )单元格包含一个棋子,则将 i 单元格中的一个棋子移动到 i+1 单元格。
求达到每个 N 单元格中正好有一块棋子的状态所需的最少操作次数。如果不可能,请打印 −1 。
思路
贪心即可。(这个格子有棋子,多的棋子向下一个地方传)
代码
// Problem: C - Sowing Stones // Contest: AtCoder - Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379) // URL: https://atcoder.jp/contests/abc379/tasks/abc379_c // Memory Limit: 1024 MB // Time Limit: 2000 ms #include<bits/stdc++.h> using namespace std; #define endl '\n' #define int __int128 namespace gtx{ // Fast IO void read(int &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');} void write(char x){putchar(x);} void write(int x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(int x,char y){write(x);write(y);} #ifndef int void read(long long &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void write(long long x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(long long x,char y){write(x);write(y);} #endif const int MAXN = 1e6+10; int p = 0; int n,m,l,x[MAXN],a[MAXN]; int get(int l,int r){ return (l+r)*(r-l+1)/2; } vector<pair<int,int>> v; signed main(){ read(n);read(m); for(int i = 1;i<=m;i++){ read(x[i]); } int tot =0 ; for(int i = 1;i<=m;i++){ read(a[i]); tot+=a[i]; v.push_back({x[i],a[i]}); } sort(v.begin(),v.end()); for(int i = 1;i<=m;i++){ x[i] = v[i-1].first; a[i] = v[i-1].second; } if(tot!=n||x[1]!=1) return puts("-1"); int ans = 0; l = 0;x[m+1]=n+1; for(int i = 1;i<m;i++){ // cout << x[i+1]-x[i] << endl; int u = a[i]; if(x[i+1]-x[i]>a[i]){ return puts("-1"); }else a[i] -= x[i+1]-x[i],ans += get(a[i],u-1); a[i+1] += a[i]; } write(ans+get(0,a[m]-1)); return 0; } } signed main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); // ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int T = 1; // gtx::read(T); while(T--) gtx::main(); return 0; }
D - Home Garden
题目大意
高桥有 10100 个花盆。最初,他没有种植任何植物。
给您 Q 个查询,请按顺序处理。
查询有以下三种类型。
1
:准备一个空花盆并放入一株植物。这里,植物的高度是 0 。2 T
:等待 T 天。在此期间,现有植物的高度会增加 T 。3 H
:收割所有高度至少达到 H 的植株,并输出收割的植株数量。收获的植物会从花盆中移出。
假设执行第一类和第三类查询所需的时间为零。
思路
用堆维护,记一个偏移量,每一个种子只会被 pop
一次,O(QlogQ)。
代码
// Problem: D - Home Garden // Contest: AtCoder - Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379) // URL: https://atcoder.jp/contests/abc379/tasks/abc379_d // Memory Limit: 1024 MB // Time Limit: 2000 ms #include<bits/stdc++.h> using namespace std; #define endl '\n' #define int long long namespace gtx{ // Fast IO void read(int &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');} void write(char x){putchar(x);} void write(int x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(int x,char y){write(x);write(y);} #ifndef int void read(long long &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void write(long long x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(long long x,char y){write(x);write(y);} #endif priority_queue<int> pq; int dlt; signed main(){ int q; read(q); while(q--){ int id;read(id); if(id==1){ pq.push(-dlt); }else if(id==2){ int num; read(num); dlt+=num; }else{ int num; read(num); int ans =0 ; while(!pq.empty()&&pq.top()+dlt>=num){ ans ++;pq.pop(); } write(ans,endl); } } return 0; } } signed main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); // ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int T = 1; // gtx::read(T); while(T--) gtx::main(); return 0; }
E - Sum of All Substrings
题目大意
给你一个长度为 N 的字符串 S ,由从 1
到 9
的数字组成。
对于每一对整数 (i,j) (1≤i≤j≤N) ,将 f(i,j) 定义为将 S 中从 i -th 到 j -th 字符的子串解释为十进制整数后得到的值。查找 N∑i=1N∑j=if(i,j) .
思路
对于同一个数我们把它拆开。
- 对于第 n 位,他可以做 n 次个位;
- 对于第 n−1 位,他可以做 n−1 次个位和 n−1 次十位;
- 对于第 n−2 位,他可以做 n−2 次个位和 n−2 次十位和 n−2 次百位;
- ......
- 对于第 1 位,他可以做每一个位置分别一次。
我们竖着看,个位的答案就是 ∑niisi%10,十位的答案为 (∑niisi/10%10+∑n−1iisi),.......
然后模拟即可。用 long long
应该是存得下的。
代码
// Problem: E - Sum of All Substrings // Contest: AtCoder - Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379) // URL: https://atcoder.jp/contests/abc379/tasks/abc379_e // Memory Limit: 1024 MB // Time Limit: 2000 ms #include<bits/stdc++.h> using namespace std; #define endl '\n' #define int __int128 namespace gtx{ // Fast IO void read(int &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');} void write(char x){putchar(x);} void write(int x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(int x,char y){write(x);write(y);} #ifndef int void read(long long &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void write(long long x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(long long x,char y){write(x);write(y);} #endif stack<int> st; int n,now,x; signed main(){ read(n); for(int i = 1;i<=n;i++){ char tmp;read(tmp); now += (tmp-'0')*i; st.push(tmp-'0'); } x=now; stack<int> ans; while(!st.empty()){ ans.push(now%10);now/=10; now += (x-=st.top()*(int)st.size()); st.pop(); } while(now){ ans.push(now%10);now/=10; } while(!ans.empty()){ write(ans.top());ans.pop(); } return 0; } } signed main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); // ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int T = 1; // gtx::read(T); while(T--) gtx::main(); return 0; }
F - Buildings 2
题目大意
问题陈述
有 N 幢楼房、 1 幢楼房、 2 幢楼房、 … 幢楼房、 N 幢楼房,自西向东依次排列成一条直线。最西边的是 1 号楼,最东边的是 N 号楼。 i (1≤i≤N) 号楼的高度为 Hi 。
对于一对整数 (i,j) (1≤i<j≤N) ,如果满足以下条件,则可以从建筑物 i 看到建筑物 j 。
- 在建筑物 i 和 j 之间,没有比建筑物 j 更高的建筑物。换句话说,没有整数 k (i<k<j) 使得 Hk>Hj 。
给你提供了 Q 个查询。在 i -查询中,给定一对整数 (li,ri) (li<ri) ,求从 li 和 ri 两座建筑物可以看到 ri 东面的建筑物(即 ri+1, ri+2, …, N )的数量。
思路
注意:i 能看到 j 并不代表 hi<hj。
我们先计算 minni 代表 i 后面能看见几栋楼(并且 hi<hj)。这里很明显使用单调栈。
所以能看见的建筑就是必须要比 rimaxp=li−1hp 还要大。
就是求 minnmaxposrip=li−1hp。这里使用线段树来实现。
代码
// Problem: F - Buildings 2 // Contest: AtCoder - Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379) // URL: https://atcoder.jp/contests/abc379/tasks/abc379_f // Memory Limit: 1024 MB // Time Limit: 2000 ms #include<bits/stdc++.h> using namespace std; #define endl '\n' //#define int long long namespace gtx{ // Fast IO void read(int &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');} void write(char x){putchar(x);} void write(int x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(int x,char y){write(x);write(y);} #ifndef int void read(long long &x){ x = 0;int h = 1;char tmp; do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp)); while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar(); x*=h; } void write(long long x){ if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0; do{st[++tot]=x%10,x/=10;} while(x); while(tot){putchar(st[tot--]+'0');} } void write(long long x,char y){write(x);write(y);} #endif deque<pair<int,int>> st; const int MAXN = 2e5+10; int n,m,a[MAXN],minn[MAXN]; struct node{ int l,r; pair<int,int> s; }tree[MAXN<<3]; void pushup(int k){ tree[k].s = min(tree[k*2].s,tree[k*2+1].s); } void build(int k,int l,int r){ tree[k].l = l; tree[k].r = r; if(l==r) return tree[k].s={minn[l],l},void(); int mid = (l+r)>>1; return build(k*2,l,mid),build(k*2+1,mid+1,r),pushup(k); } pair<int,int> ask(int k,int l,int r){ if(tree[k].r<l||tree[k].l>r) return {0x3f3f3f3f,0}; if(tree[k].r<=r&&tree[k].l>=l){ return tree[k].s; } return min(ask(k*2,l,r),ask(k*2+1,l,r)); } signed main(){ read(n);read(m); for(int i = 1;i<=n;i++){ read(a[i]); } for(int i = n;i>=1;i--){ while(!st.empty()&&st.back().second<a[i]) st.pop_back(); minn[i] = st.size();st.push_back({i,a[i]}); } build(1,1,n); for(int i = 1;i<=m;i++){ int l,r; read(l);read(r); write(minn[ask(1,l+1,r).second],endl); } return 0; } } signed main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); // ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); int T = 1; // gtx::read(T); while(T--) gtx::main(); return 0; }
G - Count Grid 3-coloring
题目大意
问题陈述
给你一个网格 S ,网格中有 H 行和 W 列,分别由 1
、2
、3
和 ?
组成。第 i 行和第 j 列上的字符是 Si,j 。
将 S 中的每个?
替换为1
、2
或3
,我们可以得到 3q 个不同的网格,其中 q 是?
的个数。在这些网格中,有多少满足以下条件?请打印模数 998244353 。
- 任意两个相邻(共边)的单元格包含不同的数字。
思路
代码
本文作者:辜铜星
本文链接:https://www.cnblogs.com/gutongxing/p/18537394
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步