Loading [MathJax]/jax/output/CommonHTML/jax.js

Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379)题解

总体情况

image
image

A - Cyclic

题意

给你一个三位整数 N ,其中每个数字都是介于 19 之间的整数。

a , b , c 分别是 N 的百位、十位和个位数。打印一个按此顺序排列 bca 所组成的整数,以及一个按此顺序排列 cab 所组成的整数。

思路

直接模拟即可。

代码

// 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 表示。

如果 Si 个字符是 "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 个单元格,编号从 1N 。最初, M 个单元格中包含了棋子,而 Xi 个单元格中包含了 Ai 个棋子 (1iM)

您可以执行以下任意次数(可能为零)的操作:

  • 如果 i1iN1 )单元格包含一个棋子,则将 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 ,由从 19 的数字组成。

对于每一对整数 (i,j) (1ijN) ,将 f(i,j) 定义为将 S 中从 i -th 到 j -th 字符的子串解释为十进制整数后得到的值。查找 Ni=1Nj=if(i,j) .

思路

对于同一个数我们把它拆开。

  • 对于第 n 位,他可以做 n 次个位;
  • 对于第 n1 位,他可以做 n1 次个位和 n1 次十位;
  • 对于第 n2 位,他可以做 n2 次个位和 n2 次十位和 n2 次百位;
  • ......
  • 对于第 1 位,他可以做每一个位置分别一次。

我们竖着看,个位的答案就是 niisi%10,十位的答案为 (niisi/10%10+n1iisi),.......

然后模拟即可。用 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 (1iN) 号楼的高度为 Hi

对于一对整数 (i,j) (1i<jN) ,如果满足以下条件,则可以从建筑物 i 看到建筑物 j

  • 在建筑物 ij 之间,没有比建筑物 j 更高的建筑物。换句话说,没有整数 k (i<k<j) 使得 Hk>Hj

给你提供了 Q 个查询。在 i -查询中,给定一对整数 (li,ri) (li<ri) ,求从 liri 两座建筑物可以看到 ri 东面的建筑物(即 ri+1, ri+2, , N )的数量。

思路

注意:i 能看到 j 并不代表 hi<hj

我们先计算 minni 代表 i 后面能看见几栋楼(并且 hi<hj)。这里很明显使用单调栈。

所以能看见的建筑就是必须要比 rimaxp=li1hp 还要大。

就是求 minnmaxposrip=li1hp。这里使用线段树来实现。

代码

// 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 列,分别由 123?组成。第 i 行和第 j 列上的字符是 Si,j

S 中的每个?替换为123,我们可以得到 3q 个不同的网格,其中 q?的个数。在这些网格中,有多少满足以下条件?请打印模数 998244353

  • 任意两个相邻(共边)的单元格包含不同的数字。

思路

代码

本文作者:辜铜星

本文链接:https://www.cnblogs.com/gutongxing/p/18537394

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   辜铜星  阅读(319)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起