AtCoder Beginner Contest 381 題解

辜铜星發表於2024-11-22

總體情況

image

A - 11/22 String

題目描述

本問題中 11/22 字串的定義與問題 C 和 E 中的定義相同。

當字串 \(T\) 滿足以下所有條件時,我們稱它為11/22 字串

  • \(|T|\) 是奇數。這裡, \(|T|\) 表示 \(T\) 的長度。
  • \(1\)\((\frac{|T|+1}{2} - 1)\) 的字元都是 "1"。
  • \((\frac{|T|+1}{2})\) -th字元是/
  • \((\frac{|T|+1}{2} + 1)\) -th到 \(|T|\) -th字元都是 "2"。

例如,11/22111/222/是 11/22 字串,但11221/22211/22222/11/2/2/211則不是。

給定長度為 \(N\) 的字串 \(S\)12/組成,判斷 \(S\) 是否是 11/22 字串。

思路分析

直接模擬即可。

程式碼

// Problem: A - 11/22 String
// Contest: AtCoder - AtCoder Beginner Contest 381
// URL: https://atcoder.jp/contests/abc381/tasks/abc381_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(){
		int n;
		read(n);
		if(n&1){
			for(int i = 1;i<=n/2;i++){
				char tmp;
				read(tmp);
				if(tmp!='1') return puts("No"),0;
			}
			char tmp;read(tmp);
			if(tmp!='/') return puts("No"),0;
			for(int i = 1;i<=n/2;i++){
				char tmp;
				read(tmp);
				if(tmp!='2') return puts("No"),0;
			}
			puts("Yes");
		}else puts("No");
		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 - 1122 String

題目描述

當且僅當字串 \(T\) 滿足以下三個條件時,它才被稱為 1122 字串

  • \(\lvert T \rvert\) 是偶數。這裡, \(\lvert T \rvert\) 表示 \(T\) 的長度。
  • 對於每個滿足 \(1\leq i\leq \frac{|T|}{2}\) 條件的整數 \(i\) 來說, \(T\)\((2i-1)\) -th 字元和 \(2i\) -th 字元是相等的。
  • 每個字元在 \(T\) 中出現的次數正好是 0 或 2。也就是說, \(T\) 中包含的每個字元在 \(T\) 中恰好出現兩次。

給定一個由小寫英文字母組成的字串 \(S\) ,如果 \(S\) 是一個 1122 字串,則列印 "是",否則列印 "否"。

思路分析

也是直接按照題意模擬即可。

程式碼

// Problem: B - 1122 String
// Contest: AtCoder - AtCoder Beginner Contest 381
// URL: https://atcoder.jp/contests/abc381/tasks/abc381_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(){
		map<char,int> mp;
		string s;
		cin >> s;
		if(s.size()&1) return puts("No"),0;
		for(int i = 1;i<=(int)s.size()/2;i++){
			if(s[2*i-2]!=s[2*i-1]) return puts("No"),0;
		}
		for(char i:s) mp[i]++;
		for(auto tmp:mp) if(tmp.second!=2) return puts("No"),0;
		puts("Yes");
		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 - 11/22 Substring

題目描述

本問題中 11/22 字串的定義與問題 A 和 E 中的定義相同。

滿足以下所有條件的字串 \(T\) 稱為 11/22 字串

  • \(|T|\) 是奇數。這裡, \(|T|\) 表示 \(T\) 的長度。
  • \(1\)\((\frac{|T|+1}{2} - 1)\) 的字元都是 "1"。
  • \((\frac{|T|+1}{2})\) -th字元是/
  • \((\frac{|T|+1}{2} + 1)\)\(|T|\) 的字元都是 "2"。

例如,11/22111/222/是 11/22 字串,但11221/22211/22222/11/2/2/211則不是。

給你一個長度為 \(N\) 的字串 \(S\) ,它由 12/組成,其中 \(S\) 包含至少一個 /
請找出長度為 11/22 的 \(S\) 的(連續)子串的最大長度。

思路分析

列舉每一個 / 字元,按照順序暴力找就行。

程式碼

// Problem: C - 11/22 Substring
// Contest: AtCoder - AtCoder Beginner Contest 381
// URL: https://atcoder.jp/contests/abc381/tasks/abc381_c
// 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;
		cin>>n;
		bool tmp=0;
		// vector<pair<int,int>> v;
		int ans = 0;
		string s;
		cin >>s;
		vector<int> v;
		for(int i = 0;i<s.size();i++){
			if(s[i]=='/') v.push_back(i);
		}
		for(int j:v){
			int cnt1 = 0;
			for(int i = j-1;~i;i--){
				if(s[i]!='1') break;
				cnt1++;
			}
			int cnt2 = 0;
			for(int i = j+1;i<s.size();i++){
				if(s[i]!='2') break;
				cnt2++;
			}
			ans = max(ans,min(cnt1,cnt2));
		}
		write(1+2*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;
}

D - 1122 Substring

題目描述

一個由正整數(可能為空)組成的序列 \(X = (X_1, X_2, \ldots)\) 當且僅當它滿足以下三個條件時,才被稱為1122 序列:(1122 序列的定義與問題 F 中的定義相同)。

  • \(\lvert X \rvert\) 是偶數。這裡, \(\lvert X \rvert\) 表示 \(X\) 的長度。
  • 對於滿足 \(1\leq i\leq \frac{|X|}{2}\) 的每個整數 \(i\)\(X_{2i-1}\)\(X_{2i}\) 都相等。
  • 每個正整數要麼完全不出現在 \(X\) 中,要麼正好出現兩次。也就是說, \(X\) 中包含的每個正整數在 \(X\) 中恰好出現兩次。

給定長度為 \(N\) 的由正整陣列成的序列 \(A = (A_1, A_2, \ldots, A_N)\) ,列印 \(A\) 的一個 (連續)子陣列 的最大長度,該陣列是一個 1122 序列。

思路分析

直接雙指標模擬即可。

程式碼

// Problem: D - 1122 Substring
// Contest: AtCoder - AtCoder Beginner Contest 381
// URL: https://atcoder.jp/contests/abc381/tasks/abc381_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
	const int MAXN = 2e5+10;
	int n,a[MAXN];
	signed main(){
		read(n);
		map<int,int> mp;
		for(int i = 1;i<=n;i++) read(a[i]);
		int r = 1;
		int ans = 0;
		bool tmp = 0;
		for(int l = 1;l<=n;l++){
				mp[a[l-1]] = 0;
			if(a[l]==a[l+1]) ans = max(ans,2);
			if(a[l]==a[l+1]&&a[l+2]!=a[l]){
				if(tmp) r = l;
				while(r<=n){
					if(a[r]==a[r+1]&&mp[a[r]]!=2){
						mp[a[r]] = 2;
						r+=2;
					}else break;
				}
				ans = max(ans,r-l);
				l++;
				tmp=0;
			}else tmp=1;
		}
		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;
}

E - 11/22 Subsequence

題目描述

本問題中 11/22 字串的定義與問題 A 和 C 中的定義相同。

當字串 \(T\) 滿足以下所有條件時,我們稱它為11/22 字串

  • \(|T|\) 是奇數。這裡, \(|T|\) 表示 \(T\) 的長度。
  • \(1\)\((\frac{|T|+1}{2} - 1)\) 的字元都是 "1"。
  • \((\frac{|T|+1}{2})\) -th字元是/
  • \((\frac{|T|+1}{2} + 1)\) -th到 \(|T|\) -th字元都是 "2"。

例如,11/22111/222/是 11/22 字串,但11221/22211/22222/11/2/2/211則不是。

給定長度為 \(N\) 的字串 \(S\) ,由12/組成,處理 \(Q\) 個查詢。

每個查詢提供兩個整數 \(L\)\(R\) 。假設 \(T\)\(S\) 中從 \(L\) -th 到 \(R\) -th 字元的(連續)子串。求 \(T\)(不一定連續)子串的最大長度,該子串是一個 11/22 字串。如果不存在這樣的子序列,則列印0

思路分析

對於給定一個位置,它是 /,那麼他的答案明顯是前面 1 的個數與後面 2 的個數的較小值。

觀察這個式子,前面 1 的個數上升,後面 2 的個數下降,所以他們的較小值一定是一個單峰函式,直接使用 三分法。(由於本人的三分寫的很逆天,所以求出來的一定是在他的上下 1000 個以內……

程式碼

// Problem: E - 11/22 Subsequence
// Contest: AtCoder - AtCoder Beginner Contest 381
// URL: https://atcoder.jp/contests/abc381/tasks/abc381_e
// Memory Limit: 1024 MB
// Time Limit: 3000 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
	const int MAXN = 1e5+10;
	int n,q;
	vector<int> v;
	char a[MAXN];
	int qz1[MAXN],qz2[MAXN];
	int calc(int l,int r,int u){
		return 2*min(qz1[u]-qz1[l-1],qz2[r]-qz2[u-1])+1;
	}
	signed main(){
		read(n);read(q);
		for(int i = 1;i<=n;i++){
			read(a[i]);
			qz1[i] = qz1[i-1];
			qz2[i] = qz2[i-1];
			if(a[i]=='1') qz1[i]++;
			if(a[i]=='2') qz2[i]++;
			if(a[i]=='/') v.push_back(i);
		}
		for(int i = 1;i<=q;i++){
			int l,r;
			read(l);read(r);
			auto tmp = lower_bound(v.begin(),v.end(),l);
			if(tmp==v.end()){
				puts("0");
				continue;
			}
			auto end = upper_bound(v.begin(),v.end(),r);
			if(end==v.begin()){
				puts("0");
				continue;
			}
			--end;
			if((end-v.begin())<(tmp-v.begin())){
				puts("0");
				continue;
			}
			auto ls = tmp;
			auto rs = end;
			int ans = 1;
			while(rs-ls>2){
				auto lmid = ls+(int)(rs-ls)/3;
				auto rmid = ls+2*(int)(rs-ls)/3;
				if(calc(l,r,*lmid)<calc(l,r,*rmid)) ls = lmid;
				else rs = rmid;
			}
			for(auto i = max(tmp,ls-min(1000,(int)(ls-v.begin())));i<=min(end,ls+min(1000,(int)(v.end()-ls-1)));i++){
				ans = max(ans,calc(l,r,*i));
			}

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;
}

相關文章