目录
E - K-th Largest Connected Components
本场链接:
AtCoder Beginner Contest 372
A - delete .
题意:
给定字符串,删除字符串中的'.',输出剩余的字符串。
思路:
遍历字符串,不是'.'就输出。
代码:
//AtCoder Beginner Contest 372
//A - delete
//https://atcoder.jp/contests/abc372/tasks/abc372_a
//Time Limit: 2 sec
//Memory Limit: 1024 MB
//
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N=2e5+5;
const int mod=1e9;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
string s;
cin>>s;
for(ll i=0;i<s.length();i++){
if(s[i]!='.'){
cout<<s[i];
}
}
return 0;
}
B - 3^A
题意:
可以选择N个数(1<=N<=20),这N个数的范围是(0≤Ai≤10) (1≤i≤N),将每个数都做成3的幂次进行求和,输出N和这个N个数。即:
思路:
先预处理3的整数次幂存入数组,在跑一边dfs即可。
dfs的流程:
1.从大往小深搜,避免超时。
2.先将当前次幂相加,将次幂压入答案,再将次幂弹出,跳过此次。
3.临界条件的处理:
(1):当sum>M时候return
(2):当x<0时候return
(3):当已经输出过答案的时候return
(4):当sum==M时候,对vector<ll>v.size()进行判断,>20return,否则,将f标记为1,输出答案。
代码:
//AtCoder Beginner Contest 372
//B - 3^A
//https://atcoder.jp/contests/abc372/tasks/abc372_b
//Time Limit: 2 sec
//Memory Limit: 1024 MB
//
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N=2e5+5;
const int mod=1e9;
int f=0;
ll jie[40];
ll M;
void Init() {
jie[0]=1;
for(ll i=1; i<=30; i++) {
jie[i]=jie[i-1]*3;
}
}
void dfs(ll x,ll sum,vector<ll>&v) {
if(f) {
return;
}
if(x<0) {
return;
}
if(sum==M) {
ll siz=v.size();
if(siz>20) {
return;
}
f=1;
cout<<siz<<endl;
int flag=0;
for(ll i=0; i<siz; i++) {
if(!flag) {
cout<<v[i];
flag=1;
} else {
cout<<" "<<v[i];
}
}
cout<<endl;
return ;
}
if(sum>M) {
return;
}
v.push_back(x);
dfs(x,sum+jie[x],v);
v.pop_back();
dfs(x-1,sum,v);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
Init();
cin>>M;
vector<ll>v;
dfs(20,0,v);
return 0;
}
C - Count ABC Again
题意:
给定一个字符串S。有q次机会,每次会选定字符串中的一个位置x,将其改为字符c。输出每次修改后字符串S中子串"ABC"的个数。
思路:
先统计原始字符串S中"ABC"的数量ans。每次查询时,对[x-2,x-1,x],[x-1,x,x+1],[x,x+1,x+2]这三个区间如果存在,分别进行S[pos1]=='A'&&S[pos2]=='B'&&S[pos3]=='C'进行判断,当条件成立时,先将ans--。再对修改之后的S中[x-2,x-1,x],[x-1,x,x+1],[x,x+1,x+2]进行同样的判断,当上述条件依然成立时,ans++,输出ans的值并换行。
代码:
//AtCoder Beginner Contest 372
//C - Count ABC Again
//https://atcoder.jp/contests/abc372/tasks/abc372_c
//Time Limit: 2 sec
//Memory Limit: 1024 MB
//
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,q;
string s;
int ans=0;
void Init() {
cin>>n>>q;
cin>>s;
s=" "+s;
for(int i=1; i<=n-2; i++) {
if(s[i]=='A'&&s[i+1]=='B'&&s[i+2]=='C')
ans++;
}
}
void Sovle() {
while(q--) {
int x;
char y;
cin>>x>>y;
int sizz=s.size();
if(x>1&&s[x]=='C'&&s[x-1]=='B'&&s[x-2]=='A')
ans--;
if(x<sizz-2&&s[x]=='A'&&s[x+1]=='B'&&s[x+2] == 'C')
ans--;
if(x>1&&x<sizz-1&&s[x - 1]=='A'&&s[x]=='B'&&s[x+1]=='C')
ans--;
s[x]=y;
if(x>1&&s[x]=='C'&&s[x-1]=='B'&&s[x-2]=='A')
ans++;
if(x<sizz-2&&s[x]=='A'&&s[x+1]=='B'&&s[x+2]=='C')
ans++;
if(x>1&&x<sizz-1&&s[x-1]=='A'&&s[x]=='B'&&s[x+1]=='C')
ans++;
cout<<ans<<endl;
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
Init();
Sovle();
return 0;
}
D - Buildings
题意:
有n个建筑物,它们有不同的高度ai。求建筑物 i 之后有多少个 j 使得 建筑物(i,j)中的全都小于aj(1<=i<j<=n)。
思路:
用栈模拟这个操作,建筑物的下标从0开始到n-1结束,从n-2遍历到0,循环直到st.size()==0||a[st.top()]<a[i](栈顶的高度比当前元素小)结束循环,将建筑物i+1的下标压入栈,建筑物i的答案就是st.size()。
代码:
//AtCoder Beginner Contest 372
//D - Buildings
//https://atcoder.jp/contests/abc372/tasks/abc372_d
//Time Limit: 2 sec
//Memory Limit: 1024 MB
//
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N=2e5+5;
const int mod=1e9;
int ans[N];
int a[N];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
for(int i=0; i<n; i++) {
cin>>a[i];
}
stack<int>st;
for(int i=n-2;i>=0;i--){
while(st.size()&&a[st.top()]<a[i+1]){
st.pop();
}
st.push(i+1);
ans[i]=st.size();
}
cout<<ans[0];
for(int i=1;i<n;i++){
cout<<" "<<ans[i];
}
return 0;
}
E - K-th Largest Connected Components
题意:
给定n个结点,编号从1开始到n。给定q次操作op,每次操作分为1或2。op==1时,在结点u,v之间添加一条边。op==2时,输出与u节点相连的第k大的节点,特别地,当与u结点相连的个数小于k时,输出-1。
思路:
运用并查集加上set进行模拟。先将fa,ss进行初始化。在进行Merge操作时,先查看fx和fy的边数大小,如果fx的边数大,则交换fx,fy。将边数小的祖先fx的边插入到边数多的祖先fy中,因为set中的关键字不会重复,所以我们可以直接插入。最后将fx的祖先改为fy。
在进行Sovle操作时,先找到x的祖先fx,判断fx的边数大小,小于k输出-1。因为set按照关键字从小到大排序,所以利用迭代器找到set的末尾,利用while找到第k大的结点,并且输出。
代码:
//AtCoder Beginner Contest 372
//E - K-th Largest Connected Components
//https://atcoder.jp/contests/abc372/tasks/abc372_e
//Time Limit: 2 sec
//Memory Limit: 1024 MB
//
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N=2e5+5;
const int mod=1e9;
int fa[N];
vector<set<int>>ss(N);
int Find(int x){
return fa[x]==x?x:Find(fa[x]);
}
void Merge(int x,int y){
int fx=Find(x),fy=Find(y);
if(fx==fy)return;
if(ss[fx].size()>ss[fy].size()){
swap(fx,fy);
}
for(auto u:ss[fx]){
ss[fy].insert(u);
}
fa[fx]=fy;
}
int Solve(int x,int k){
int fx=Find(x);
int sizz=ss[fx].size();
if(sizz<k)return -1;
set<int>::iterator it=ss[fx].end();
while(k--){
it--;
}
return *it;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++){
fa[i]=i;
ss[i].insert(i);
}
while(q--) {
int op;
cin>>op;
if(op==1) {
int u,v;
cin>>u>>v;
Merge(u,v);
} else {
int u,k;
cin>>u>>k;
// cout<<"ans=";
cout<<Solve(u,k)<<endl;;
}
}
return 0;
}