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

辜铜星發表於2024-11-09

總體情況

image
image

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\) 個單元格中包含了棋子,而 \(X_i\) 個單元格中包含了 \(A_i\) 個棋子 \((1 \leq i \leq M)\)

您可以執行以下任意次數(可能為零)的操作:

  • 如果 \(i\)\(1 \leq i \leq 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

題目大意

高橋有 \(10^{100}\) 個花盆。最初,他沒有種植任何植物。

給您 \(Q\) 個查詢,請按順序處理。

查詢有以下三種型別。

  • 1:準備一個空花盆並放入一株植物。這裡,植物的高度是 \(0\)
  • 2 T:等待 \(T\) 天。在此期間,現有植物的高度會增加 \(T\)
  • 3 H:收割所有高度至少達到 \(H\) 的植株,並輸出收割的植株數量。收穫的植物會從花盆中移出。

假設執行第一類和第三類查詢所需的時間為零。

思路

用堆維護,記一個偏移量,每一個種子只會被 pop 一次,\(O(Q\log Q)\)

程式碼

// 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) \ (1\leq i\leq j\leq N)\) ,將 \(f(i, j)\) 定義為將 \(S\) 中從 \(i\) -th 到 \(j\) -th 字元的子串解釋為十進位制整數後得到的值。查詢 \(\displaystyle \sum_{i=1}^N \sum_{j=i}^N f(i, j)\) .

思路

對於同一個數我們把它拆開。

  • 對於第 \(n\) 位,他可以做 \(n\) 次個位;
  • 對於第 \(n-1\) 位,他可以做 \(n-1\) 次個位和 \(n-1\) 次十位;
  • 對於第 \(n-2\) 位,他可以做 \(n-2\) 次個位和 \(n-2\) 次十位和 \(n-2\) 次百位;
  • ......
  • 對於第 \(1\) 位,他可以做每一個位置分別一次。

我們豎著看,個位的答案就是 \(\sum_i^n is_i\%10\),十位的答案為 \((\sum_i^n is_i/10\%10+\sum_i^{n-1}is_i)%10\),.......

然後模擬即可。用 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\) 幢樓房、 \(\ldots\) 幢樓房、 \(N\) 幢樓房,自西向東依次排列成一條直線。最西邊的是 \(1\) 號樓,最東邊的是 \(N\) 號樓。 \(i\ (1\leq i\leq N)\) 號樓的高度為 \(H_i\)

對於一對整數 \((i,j)\ (1\leq i\lt j\leq N)\) ,如果滿足以下條件,則可以從建築物 \(i\) 看到建築物 \(j\)

  • 在建築物 \(i\)\(j\) 之間,沒有比建築物 \(j\) 更高的建築物。換句話說,沒有整數 \(k\ (i\lt k\lt j)\) 使得 \(H_k > H_j\)

給你提供了 \(Q\) 個查詢。在 \(i\) -查詢中,給定一對整數 \((l_i,r_i)\ (l_i\lt r_i)\) ,求從 \(l_i\)\(r_i\) 兩座建築物可以看到 \(r_i\) 東面的建築物(即 \(r_i + 1\), \(r_i + 2\), \(\ldots\), \(N\) )的數量。

思路

注意:\(i\) 能看到 \(j\) 並不代表 \(h_i<h_j\)

我們先計算 \(minn_i\) 代表 \(i\) 後面能看見幾棟樓(並且 \(h_i<h_j\))。這裡很明顯使用單調棧。

所以能看見的建築就是必須要比 \(\displaystyle\max_{p=l_i-1}^{r_i}h_p\) 還要大。

就是求 \(minn_{\displaystyle\text{maxpos}_{p=l_i-1}^{r_i}h_p}\)。這裡使用線段樹來實現。

程式碼

// 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\) 列上的字元是 \(S_{i,j}\)

\(S\) 中的每個?替換為123,我們可以得到 \(3^q\) 個不同的網格,其中 \(q\)?的個數。在這些網格中,有多少滿足以下條件?請列印模數 \(998244353\)

  • 任意兩個相鄰(共邊)的單元格包含不同的數字。

思路

程式碼


相關文章