AtCoder Beginner Contest 372

目录

A - delete .

题意:

思路:

代码:

B - 3^A

题意:

思路:

dfs的流程:

代码:

C - Count ABC Again

题意:

思路:

代码:

D - Buildings

题意:

思路:

代码:

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个数。即:

\sum_{i=1}^{N}3^{Ai}=M

思路:

        先预处理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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值