AtCoder Beginner Contest 328

AtCoder Beginner Contest 328

比赛链接: https://atcoder.jp/contests/abc328

A - Not Too Hard

Print the total score for all problems with a score of X or less.
#include<bits/stdc++.h>
#define int long long
using namespace std;

signed main(){
	std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0);
	int n,a; cin>>n>>a;
	int ans = 0;
	for(int i = 1; i <= n; i++){
		int x; cin>>x;
		if(x <= a) ans += x;
	}
	cout<<ans<<endl;
}

B - 11/11

考虑到$N$和$D$都很小....直接暴力判断一下是不是全一样就行了

#include<bits/stdc++.h>
#define int long long
using namespace std;

signed main(){
	std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0);
	int n; cin>>n;
	vector<int> d(n + 1);
	int ans = 0;
	for(int i = 1; i <= n; i++){
		cin>>d[i];
		if(i >= 10){
			if(i % 10 != (i / 10) % 10) continue;
		}
		if(i == 100){
			continue;
		}
		int now = (i % 10);
		while(now <= d[i]){
			ans++;
			now = now * 10 + (i % 10);
		}
	}
	cout<<ans<<endl;
}

C - Consecutive

前缀和,可以发现一段中满足$l_i \leq p \leq r_i-1$ and $S_p = S_{p+1}$是递增的,而且前后不影响

#include<bits/stdc++.h>
#define int long long
using namespace std;

signed main(){
	std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0);
	int n,q; cin>>n>>q;
	string s; cin>>s; s = " " + s + " ";
	vector<int> ct(n + 2);
	ct[0] = 0;
	for(int i = 1; i <= n; i++){
		if(s[i] == s[i + 1]) ct[i] = ct[i - 1] + 1;
		else ct[i] = ct[i - 1];
	}
	while(q--){
		int l, r; cin>>l>>r;
		cout<<ct[r - 1] - ct[l - 1]<<endl;
	}
}

D - Take ABC

模拟一个栈,检查后三位是不是'ABC',是的话直接弹出

#include<bits/stdc++.h>
#define int long long
using namespace std;

signed main(){
	std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0);
	string s; cin>>s;
	string st;
	for(int i = 0; i < s.length(); i++){
		st.push_back(s[i]);
		if(st.length() < 3) continue;
		if( st[st.length() - 3] == 'A' &&
			st[st.length() - 2] == 'B' &&
			st[st.length() - 1] == 'C'){
			st = st.substr(0, st.length() - 3);
		}
	}
	cout<<st<<endl;
}

E - Modulo MST

可以发现$N$特别小,加上是无向简单图,直接考虑暴力做法就行了。

暴力就是加点法去生成树

DFS里就是每次检查一下还有那些点没被连上,并且与已经被连上的点相邻,就可以连它

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 100;
vector<int> G[N];
int W[N][N];
int vis[N];
int n,m,k; 
int ans = 1e15 + 20;
int sum = 0;

void dfs(int ct){
	for(int i = 1; i <= n; i++){
		if(!vis[i]){
			for(int j : G[i]){
				if(vis[j]){
					vis[i] = 1;
					sum += W[i][j];
					dfs(ct + 1);
					sum -= W[i][j];
					vis[i] = 0;
				}
			}
		}
	}
	if(ct == n){
		ans = min(ans, sum % k);
	}
}

signed main(){
	std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0);
	cin>>n>>m>>k;
	for(int i = 1; i <= m; i++){
		int u,v,w; cin>>u>>v>>w;
		G[u].push_back(v); W[u][v] = w;
		G[v].push_back(u); W[v][u] = w;
	}
	for(int i = 0; i < N; i++) vis[i] = 0;
	vis[1] = 1;
	sum = 0;
	dfs(1);
	cout<<ans<<endl;
}

F - Good Set Query

带权并查集,套板子就行了

这题主要的阻碍在于参照物太多了,每次给出的都是相对的属性,考虑用并查集确定统一的参照物以便于对比。

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 2e5 + 10;

int pre[N];
int val[N];

int find(int x) {
	if(x!=pre[x]) {
		int t=pre[x];
		pre[x]=find(pre[x]);
		val[x]+=val[t];
	}
	return pre[x];
}

void merge(int x,int y,int s) {
	if (find(x)!=find(y)) {
		int t = find(x);
		pre[find(x)]=find(y);
		val[t]=val[y]-val[x]+s;
	}
}

signed main(){
	std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0);
	int n, q; cin>>n>>q;
	set<int> ans;
	for(int i = 1; i <= n; i++) pre[i] = i;
	for(int i = 1; i <= q; i++){
		int a,b,d; cin>>a>>b>>d;
		int fa = find(a); 
		int fb = find(b);
		if(fa != fb){
			merge(a, b, d);
			ans.insert(i);
		} else {
			if(val[a] - val[b] == d) ans.insert(i);
		}
	}
	for(int i : ans){
		cout<<i<<" ";
	}
}