[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
t 为 ABC
,则可以将
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;
}