AtCoder Beginner Contest 146解题报告

题目地址

https://atcoder.jp/contests/abc146/tasks

感觉没有什么有意思的题...

题解

A

#include 
using namespace std;

string s;

int main() {
	cin >> s; int now = 0;
	if(s[0] == 'S') {
		if(s[1] == 'U') now = 0;
		else now = 6;
	}
	if(s[0] == 'M') now = 1;
	if(s[0] == 'T') {
		if(s[1] == 'U') now = 2;
		else now = 4;
	}
	if(s[0] == 'W') now = 3;
	if(s[0] == 'F') now = 5;
	printf("%d\n", 7 - now);
} 

B

#include 
using namespace std;

char s[10000];

int main() {
	int n; cin >> n;
	scanf("%s", s);
	int len = strlen(s);
	for(int i = 0; i < len; ++i) {
		s[i] -= 'A';
	}
	for(int i = 0; i < len; ++i) {
		s[i] += n;
		s[i] %= 26;
	}
	for(int i = 0; i < len; ++i) putchar(s[i] + 'A');
	return 0;
} 

C

不难发现\(n\)\(d(n)\)都是递增的。那么二分\(n\)即可。
注意数字上限是\(10^9\)。我一开始直接大力\(10^{18}\)结果wa了2发。

#include 
using namespace std;

const int N = 100010;

int n, c[N];
int x[N], y[N], deg[N], g[N];
int cnt, head[N];
struct edge {int to, nxt, id;} e[N << 1];

void ins(int u, int v, int id) {
	e[++cnt] = (edge) {v, head[u], id};
	head[u] = cnt;
} 

void dfs(int u, int fa, int col) {
	int now = 0;
	for(int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if(v == fa) continue;
		++now;
		if(now == col) ++now;
		g[e[i].id] = now;
		dfs(v, u, now);
	}
}

int main() {
	cin >> n;
	for(int i = 1; i < n; ++i) {
		cin >> x[i] >> y[i];
		deg[x[i]]++; deg[y[i]]++;
		ins(x[i], y[i], i), ins(y[i], x[i], i);
	}
	int ans = 0;
	for(int i = 1; i <= n; ++i) 
		if(deg[i] > deg[ans]) ans = i;
	cout << deg[ans] << endl;
	dfs(ans, ans, 0);
	for(int i = 1; i < n; ++i) printf("%d\n", g[i]);
} 

D

显然答案是最大度数。随便钦定个点为根然后遍历一遍,记录一下入边的颜色就可以染色了。

#include 
using namespace std;

const int N = 100010;

int n, c[N];
int x[N], y[N], deg[N], g[N];
int cnt, head[N];
struct edge {int to, nxt, id;} e[N << 1];

void ins(int u, int v, int id) {
	e[++cnt] = (edge) {v, head[u], id};
	head[u] = cnt;
} 

void dfs(int u, int fa, int col) {
	int now = 0;
	for(int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		if(v == fa) continue;
		++now;
		if(now == col) ++now;
		g[e[i].id] = now;
		dfs(v, u, now);
	}
}

int main() {
	cin >> n;
	for(int i = 1; i < n; ++i) {
		cin >> x[i] >> y[i];
		deg[x[i]]++; deg[y[i]]++;
		ins(x[i], y[i], i), ins(y[i], x[i], i);
	}
	int ans = 0;
	for(int i = 1; i <= n; ++i) 
		if(deg[i] > deg[ans]) ans = i;
	cout << deg[ans] << endl;
	dfs(ans, ans, 0);
	for(int i = 1; i < n; ++i) printf("%d\n", g[i]);
} 

E

唯一一个需要想一想的题。
考虑题目所求为\(s[r] - s[l] \equiv r - l \mod k\),移项一下就是\(s[r] - r \equiv s[l] - l \mod k\)
然后直接拿个map什么的东西算一算就行了。
注意判断\(r-l\)大于\(k\)的情况,是不合法情况。

/*
s[r] - s[l] = r - l (mod k)
s[r] - r = s[l] - l (mod k)
*/
#include 
using namespace std;

typedef long long ll;
const int N = 200010;

int n, k;
ll s[N];
mapS;

int main() {
	cin >> n >> k;
	for(int i = 1, x; i <= n; ++i) {
		cin >> x;
		s[i] = s[i - 1] + x;
	}
	S[0] = 1;
	ll ans = 0;
	int l = 0;
//	for(int i = 1; i <= n; ++i) printf("%d ", (s[i] - i + k) % k);
//	puts("");
	for(int i = 1; i <= n; ++i) {
		if(i >= k) {S[(s[l] - l + k) % k]--; ++l;}
		ans += S[(s[i] - i + k) % k];
//		printf("%d ", S[(s[i] - i + k) % k]);
		S[(s[i] - i + k) % k]++;
	}//puts("");
	printf("%lld\n", ans);
	return 0;
}

F

直接单调队列优化dp即可。dp的时候记录一下转移点。复杂度\(O(n)\)

#include 
using namespace std;

typedef long long ll;
const int N = 200010;

int n, m, f[N], g[N], st[N], top;
char s[N];
struct Node {int v, id;};
dequeq;

int main() {
	memset(g, -1, sizeof(g));
	memset(f, 0x3f, sizeof(f));
	scanf("%d%d", &n, &m);
	scanf("%s", s);
	f[0] = 0; q.push_back({f[0], 0});
	for(int i = 1; i <= n; ++i) {
		while(!q.empty() && i - q.front().id > m) q.pop_front();
		if(s[i] == '1') continue;
		if(!q.empty()) f[i] = q.front().v + 1, g[i] = q.front().id;
		while(!q.empty() && q.back().v > f[i]) q.pop_back();
		if(f[i] != 0x3f3f3f3f) q.push_back({f[i], i});
 	}
 	if(g[n] == -1) return puts("-1"), 0;
 	int now = n;
 	while(g[now] != -1) {st[++top] = now - g[now], now = g[now];}
 	while(top) printf("%d ", st[top--]);
	puts("");
}

你可能感兴趣的:(AtCoder Beginner Contest 146解题报告)