ABC329题解(A~F)

[ABC329A] Spread

题意简述

给定字符串 s s s,在 s s s 的每个字符中间加上空格后输出。

代码示例

#include<bits/stdc++.h>
using namespace std;
#define int long long
string s;
signed main(){
	cin>>s;
	for(int i=0;i<s.size();i++) cout<<s[i]<<" ";
	return 0;
}

[ABC329B] Next

题意简述

给定 n n n 个数,找到这 n n n 个数去重后的次大值,保证答案一定存在。

解题思路

我用了一个 multiset,然后 while 循环将最大值去掉。

代码示例

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
multiset<int> s;
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		s.insert(x);
	}
	int Max=*s.rbegin();
	while(*s.rbegin()==Max) s.erase(s.find(*s.rbegin()));
	cout<<*s.rbegin()<<endl;
	return 0;
}

[ABC329C] Count xxx

题意简述

给定字符串 s s s,找到 s s s 所有子串中,由单一字符组成的子串共有多少个(重复不算)。

做题思路

对于 s s s 中连续的一段单一字符构成的串,能对答案产生的贡献就是它的长度。比如 aaaaa,可以对答案产生 5 5 5 的贡献。但是还要考虑到去重,所以我们开一个数组记录每个字符连续出现的 最大长度,最后统计答案即可。

代码示例

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
string s;
int ans[30];
signed main(){
	cin>>n>>s;
	s=" "+s;
	for(int i=1;i<=n;i++){
		int nw=i;
		while(s[nw+1]==s[i]&&nw+1<=n) nw++;
		ans[s[i]-'a'+1]=max(ans[s[i]-'a'+1],nw-i+1);
		i=nw;
	}
	int num=0;
	for(int i=1;i<=26;i++) num+=ans[i];
	cout<<num<<endl;
	return 0;
}

[ABC329D] Election Quick Report

题意简述

n n n 个候选人,一开始每个人的选票为 0 0 0。给定 m m m 次投票,第 i i i 次投票后 a i a_i ai 候选人的票数加一。求出每次投票后获胜的候选人是谁。票数最多者获胜。若票数最多不唯一,编号小者获胜。

解题思路

考虑手写一个结构体,将编号和票数放在结构体中,然后用 set 来记录答案。每次投票后,没有必要删除投票前的值,因为投票会使票数加一,所以更少的票数不会对答案产生影响。

代码示例

#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node{
	int id,num;
	bool operator<(const node &b)const{
		if(num==b.num) return id<b.id;
		return num>b.num;
	}
};
int n,m,cnt[200010];
set<node> s;
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cnt[i]=0;
	for(int i=1;i<=m;i++){
		int x;
		cin>>x;
		cnt[x]++;
		s.insert({x,cnt[x]});
        //只需加入而无需删除
		cout<<(*s.begin()).id<<endl;
	}
	return 0;
}

[ABC329E] Stamp

题意简述

给定两个整数 n , m n,m n,m,两个长度分别为 n , m n,m n,m 的字符串 s , t s,t s,t。现在你有一个长度为 n n n,且由 #构成的字符串 x x x,你可以做以下操作任意多次:

选择 x x x 中的连续 m m m 个字符,替换为 t t t

确定最终能否使 s s s x x x 完全一样。

解题思路

非常巧妙,涨芝士了。

考虑反过来思考,每次从 s s s 中选一些和 t t t 一样的字符,让它们变成 #。其实相当于一个撕贴纸的过程, t t t 就是贴纸。

注意此时我们认定 #相当于任意字符。即,若 s s s 的一个子串为 #BC t t tABC,则可以将 s s s 变为 ###。因为在贴贴纸的过程中会有覆盖掉的部分,而我们不知道。

实现可以用搜索。

代码示例

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
string s,t;
bool check(int st){
	bool ck=0;
	for(int i=st,j=1;j<=m;i++,j++){
		if(s[i]!='#'){
			if(s[i]!=t[j]) return 0;
			ck=1;
		}
        //注意如果s全部为#就跳过,否则会TLE
	}
	if(ck) for(int i=st;i<=st+m-1;i++) s[i]='#';
	return ck;
}
void dfs(int l){
	//往后m位
	for(int i=l;i<=min(n-m+1,l+m);i++) if(check(i)) dfs(i);
   	//往前m位
	for(int i=l;i>=max(1ll,l-m);i--) if(check(i)) dfs(i);
}
signed main(){
	cin>>n>>m>>s>>t;
	s=" "+s,t=" "+t;
	for(int i=1;i<=n-m+1;i++) if(check(i)) dfs(i);
	for(int i=1;i<=n;i++){
		if(s[i]!='#'){
			cout<<"No"<<endl;
			return 0;
		}
	}
	cout<<"Yes"<<endl;
	return 0;
}

[ABC329F] Colored Ball

题意简述

现在有 n n n 个球和 n n n 个箱子,一开始的时候每个箱子里有一个颜色为 c i c_i ci 的球。进行 q q q 次操作,每次操作内容为:将 x x x 箱子中所有的球放到 y y y 箱子里。对于每次操作,你需要输出 y y y 箱子中的球共有多少种不同的颜色。

解题思路

双倍经验

考虑启发式合并。每次合并时将球少的合并到球多的中,就可以过了。

有个小技巧是集合可以直接交换,这个我赛后才知道。赛时写了一个数组记录每个球在哪个箱子中。

代码示例

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,q,num[200010],id[200010];
set<int> ans[200010];
signed main() {
	cin>>n>>q;
	for(int i=1,c;i<=n;i++) cin>>c,ans[i].insert(c),id[i]=i;
	while(q--){
		int x,y;
		cin>>x>>y;
		int fax=id[x],fay=id[y];
		if(ans[fax].size()>ans[fay].size()) swap(fax,fay),swap(id[x],id[y]);
		for(auto i:ans[fax]) ans[fay].insert(i);	
		ans[fax].clear();
		cout<<ans[fay].size()<<endl;
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值