AtCoder Beginner Contest 381 题解

总体情况

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;
}
posted @ 2024-11-22 21:57  辜铜星  阅读(462)  评论(0编辑  收藏  举报