Codeforces Round 699 题解

[比赛链接]

https://codeforces.com/contest/1481

[题解]

(A)

两维的坐标是独立的 , 记录向上 , 下 , 左 , 右共走的步数判断即可。

时间复杂度 : (O(N))

(B)

注意到 (max{a_{i}} leq 100) , 因此最多只会操作 (10000) 次。

不妨直接模拟这个过程 , 其必然会在 (10000) 次后停止。

时间复杂度 : (O(N ^ 3))

(C)

首先考虑第 (M) 次涂色的位置不会被更改 (因为是最后一次涂色)。不妨首先固定一个 (B_{i} = C_{M})(i) (优先考虑 (A_{i} eq B_{i}))。

然后从前向后枚举每一次涂色 , 每次仍然贪心地优先考虑 (B_{i} = C_{current} , A_{i} eq B_{i})(i) , 如果找不到则对 (M) 次涂色的位置操作一次即可。

时间复杂度 : (O(N + M))

(D)

首先 , 如果存在点对 ((u , v)) , 使得 (val_{u , v} = val_{v , u})。构造一条 (u -> v -> u -> v ...) 的路径即可。

特判这种情况 , 剩下的问题必然满足 (val_{u , v} eq val_{v , u})

(M) 是奇数 , 可构造一条在两点间来回移动的路径。

否则 , 考虑三点 (u , v , w) 使得 (val_{u , v} = val_{v , w})

(frac{M}{2}) 为奇数 , 以环上的数字的顺序不断重复即可 (如下图)。

(frac{M}{2}) 为偶数的情况类似。

时间复杂度 : (O(N ^ 2))

(E)

首先对于每种颜色 (c) 找到其最左出现的位置 (l_{c}) , 最右 (r_{c}) , 以及出现的次数 (f_{c})

一个转化是问题等价于求最多保留的数的个数。

考虑倒着动态规划 , 记 (dp_{i}) 表示后缀 ([i , n]) 最多保留的数的个数。

首先 (dp_{i}) 可以继承 (dp_{i + 1}) 的信息 (表示操作当前的左端点)

(i = l_{c}) , 显然可以保留颜色 (c) , 此时 (dp_{i} = dp_{r_{c_{i}} + 1} + f_{c})

(i eq l_{c}) , 有 (dp_{i} = cf_{c}) ((cf_{c}) 表示 (c) 在当前 ([i , n]) 中出现次数)。

时间复杂度 : (O(N))

(F)

首先找出以 (1) 为根的最长链 , 将其长度记为 (d)

因为会出现 ((d + 1)) 种不同长度的字符串 ,显然 , (answer geq d + 1)

为了使 (answer = d + 1) , 需要使所有长度为 (i) 的字符串相等。考虑求出每个深度的节点出现的次数 (a_{i})

那么等价于找出 (A) 的一个子集 , 使其和为 (X) , 将其全部涂上 "a"。

注意到不同的 (a_{i}) 至多有 (O(sqrt{N})) 种 , 不妨记录出现次数为 (i) 的深度个数 (freq_{i})

考虑动态规划 , 令 (dp_{i , j}) 表示后 (i) 种出现次数 , 总和为 (j) 是否可行。

一种朴素的转移方式是枚举 (dp_{i + 1 , j - val_{i}} , dp_{i + 1 , j - 2 cdot val_{i}} , ... dp_{i + 1 , j - freq_{i} cdot val_{i}})

进一步地 , 注意到每次转移到的节点在模 (val) 意义下同余 , 可以方便地记录 (last_{i}) 表示在模 (val) 意义下余 (i) 上次出现的位置。

这样就可以做到 (O(Nsqrt{N})) 了。

否则答案一定等于 ((d + 2)) , 下面通过构造的方式证明这一点。

考虑枚举每一层节点。记当前在第 (i) 层 , 还剩下 (m) 个字母可用 , 其中有 (y) 个为 "a"。

(a_{i} leq max{y , m - y}) , 则直接给这层节点涂上一种颜色。

否则 , 这层的非叶节点必须涂上同一种颜色 , 因为每个非叶节点子树中必然存在至少 (1) 个节点 , 非叶节点 (l geq frac{m}{2})。 又因为对于任意 (y) , (max{y , m - y} geq frac{m}{2})。 因此我们可以做到这一点。

这样就只剩下一种颜色了! 我们成功构造出了 (answer = d + 2) !

时间复杂度 : (O(Nsqrt{N}))

[代码]

(A)

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

#define rep(i , l , r) for (int i = (l); i < (r); ++i)

char s[1000005];

int main() {
	
	 int T; cin >> T;
	 while (T--) {
	 	 int xx , yy; cin >> xx >> yy;
	 	 string ss; cin >> ss;
	 	 int u = 0 , d = 0 , l = 0 , r = 0;
	 	 for (int i = 0; i < ss.size(); ++i) {
	 	 	 if (ss[i] == 'U') ++u;
			 else if (ss[i] == 'R') ++r;
			 else if (ss[i] == 'D') ++d;
			 else ++l;  	
		 }
		 if (xx > 0 && r >= xx) xx = 0;
                 if (xx < 0 && l >= -xx) xx = 0;
                 if (yy > 0 && u >= yy) yy = 0;
                 if (yy < 0 && d >= -yy) yy = 0;
                 if (xx == 0 && yy == 0) puts("YES");
                 else puts("NO");
	 }
         return 0;
}

(B)

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

#define rep(i , l , r) for (int i = (l); i < (r); ++i)

const int MN = 5e5 + 5;

int A[MN];

int main() {
	 
	 int T; scanf("%d" , &T);
	 while (T--) {
	 	 int N , K; scanf("%d%d" , &N , &K);
	 	 for (int i = 1; i <= N; ++i) scanf("%d" , &A[i]);
	 	 int ans = -1;
	 	 for (int cur = 1; cur <= K; ++cur) {
			ans = -1;
			for (int i = 1; i < N; i++) if (A[i] < A[i + 1]) { ans = i; ++A[i]; break;}
			if (ans == -1) break;
		}
		printf("%d
" , ans);
	 }
         return 0;
}

(C)

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

#define rep(i , l , r) for (int i = (l); i < (r); ++i)

const int MN = 1e6 + 5;

int N , M , A[MN] , B[MN] , C[MN] , ans[MN];
vector < int > g[MN];

inline void solve() {
	scanf("%d%d" , &N , &M);
	for (int i = 1; i <= N; ++i) g[i].clear();
	for (int i = 0; i < N; ++i) scanf("%d" , &A[i]);
	for (int i = 0; i < N; ++i) {
		scanf("%d" , &B[i]);
		if (B[i] != A[i])
			g[B[i]].emplace_back(i);
	}
	for (int i = 0; i < M; ++i)
		scanf("%d" , &C[i]);
	int last = -1;
	if ((int) g[C[M - 1]].size() > 0) {
		last = g[C[M - 1]].back();
		g[C[M - 1]].pop_back();
	} else {
		for (int i = 0; i < N; ++i) {
			if (B[i] == C[M - 1]) {
				last = i;
				break;
			}
		}
	}
	if (last == -1) {
		printf("NO
");
		return;
	}
	ans[M - 1] = last;
	for (int i = 0; i < M - 1; ++i) {
		if (g[C[i]].size() == 0)
			ans[i] = last;
		else {
			ans[i] = g[C[i]].back();
			g[C[i]].pop_back();
		}
	}
	for (int i = 1; i <= N; ++i)
		if ((int) g[i].size() > 0) {
			printf("NO
");
			return;
		}
	printf("YES
");
	for (int i = 0; i < M; ++i) {	
		if (i) putchar(' ');
		printf("%d" , ans[i] + 1);
	}
	printf("
");
}
int main() {
	 
	 int T; scanf("%d" , &T);
	 while (T--) solve();
     return 0;
}

(D)

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

#define rep(i , l , r) for (int i = (l); i < (r); ++i)

const int MN = 1005;

int N , M , has[MN][2];
char grid[MN][MN];

inline void solve() {
	scanf("%d%d" , &N , &M);
	for (int i = 0; i <= N; ++i)
		has[i][0] = has[i][1] = -1;
	for (int i = 0; i < N; ++i) {
		scanf("%s" , grid[i]);
		for (int j = 0; j < N; ++j) {
			if (i == j) continue;
			has[i][grid[i][j] - 'a'] = j;
		}
	}
	if (M & 1) {
		printf("YES
");
		for (int i = 0; i <= M; ++i) {
			if (i) putchar(' ');
			printf("%d" , (i & 1) + 1);
		}
		printf("
");
		return;
	}
	for (int i = 0; i < N; ++i)
		for (int j = i + 1; j < N; ++j)
			if (grid[i][j] == grid[j][i]) {
				printf("YES
");
				for (int k = 0; k <= M; ++k) {
					if (k) putchar(' ');
					printf("%d" , (k & 1 ? i + 1 : j + 1));
				}
				puts("");
				return;
			}
	for (int i = 0; i < N; ++i) {
		for (int j = 0; j < N; ++j) {
			if (i == j) continue;
			if (has[j][grid[i][j] - 'a'] == -1) continue;
			printf("YES
");
			int cur = has[j][grid[i][j] - 'a'];
			if ((M / 2) & 1) {
				for (int k = 0; k <= M; ++k) {
					if (k) putchar(' ');
					if (k % 4 == 0)
						printf("%d" , i + 1);
					else if (k % 4 == 2) 
						printf("%d" , cur + 1);
					else printf("%d" , j + 1);
				}
				printf("
");
				return;
			}
			printf("%d" , j + 1);
			for (int k = 0; k < M / 2; ++k)
				if (k & 1) printf(" %d" , j + 1);
				else printf(" %d" , cur + 1);
			for (int k = 0; k < M / 2; ++k)
				if (k & 1) printf(" %d" , j + 1);
				else printf(" %d" , i + 1);
			printf("
");
			return;
		}
	}
	printf("NO
");
}
int main() {
	 
	 int T; scanf("%d" , &T);
	 while (T--) solve();
         return 0;
}

(E)

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

#define rep(i , l , r) for (int i = (l); i < (r); ++i)

const int MN = 5e6 + 5;

int N , A[MN] , l[MN] , r[MN] , f[MN] , cnt[MN];

int main() {
	
	 scanf("%d" , &N);
	 for (int i = 1; i <= N; ++i) {
	 	 scanf("%d" , &A[i]); 
	 	 if (!l[A[i]]) l[A[i]] = i;
		 r[A[i]] = i; 
	 }
	 for (int i = N; i >= 1; --i) {
	 	 ++cnt[A[i]];
	 	 f[i] = f[i + 1];
	 	 if (i == l[A[i]])
	 	 	f[i] = max(f[i] , cnt[A[i]] + f[r[A[i]] + 1]);
	 	 else
	 	 	f[i] = max(f[i] , cnt[A[i]]);
	 }
	 printf("%d
" , N - f[1]);
         return 0;
}

(F)

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

#define rep(i , l , r) for (int i = (l); i < (r); ++i)

typedef pair < int , int > pii;

#define mp make_pair
#define F first
#define S second

const int MN = 1e5 + 5 , SQ = 500;

int N , X , mx , sz[MN] , dp[SQ][MN] , f[MN];
char c[MN];
vector < pii > v , v2;
vector < int > g[MN] , cur[MN];
pair < int , char > a , b;

inline void go(int i , int j) {
	if (i == (int) v2.size())
		return;
	while (!dp[i + 1][j]) {
		++f[v2[i].first];
		j -= v2[i].first;
	}
	go(i + 1 , j);
}
inline void chkmin(int &x , int y) {
	x = min(x , y);
}
inline void chkmax(int &x , int y) {
	x = max(x , y);
}
inline bool cmp(int u , int v) {
	return sz[u] < sz[v];
}
inline int DFS(int u , int d) {
	chkmax(mx , d);
	cur[d].emplace_back(u); sz[u] = 1;
	for (int v : g[u])
		sz[u] += DFS(v , d + 1);
	return sz[u];
}

int main() {
	 
	 scanf("%d%d" , &N , &X);
	 a = mp(X , 'a'); b = mp(N - X , 'b');
	 if (a > b) swap(a , b);
	 for (int i = 2; i <= N; ++i) {
	 	 int x; scanf("%d" , &x);
	 	 g[x].emplace_back(i);
	 }
	 DFS(1 , 0);
	 for (int i = 0; i <= mx; ++i)
	 	v.emplace_back(mp((int) cur[i].size() , i));
	 sort(v.begin() , v.end());
	 for (int i = 0; i < v.size(); ++i)
	 	 if (i == 0 || v[i].F != v[i - 1].F) 
	 		 v2.emplace_back(mp(v[i].F , 1));
	 	 else
		  	 ++v2.back().second;
	 dp[(int)v2.size()][0] = true;
	 for (int i = (int) v2.size() - 1; i >= 0; --i) {
	 	 int val = v2[i].first , frq = v2[i].second;
	 	 vector < int > last (val , -1);
	 	 for (int j = 0; j <= X; ++j) {
	 	 	 if (dp[i + 1][j] == true)
			   	last[j % val] = j;
			 if (last[j % val] == -1 || ((j - last[j % val]) / val) > frq)
			 	dp[i][j] = false;
			 else 
			 	dp[i][j] = true;	
		 }
	 }
	 if (dp[0][X]) {
	 	 go(0 , a.F);
	 	 for (int i = 1; i <= N; ++i) c[i - 1] = b.S;
	 	 for (int i = 0; i <= mx; ++i) {
	 	 	 if (f[(int) cur[i].size()] == 0) continue;
			 --f[(int) cur[i].size()];	 
			 for (auto x : cur[i])
			 	 c[x - 1] = a.S;
		 } 
		 printf("%d
" , mx + 1); c[N] = '';
		 puts(c);
		 return 0;
	 }
	 printf("%d
" , mx + 2);
	 for (int i = 0; i <= mx; ++i) {
	 	 sort(cur[i].begin() , cur[i].end() , cmp);
	 	 if (a.F < b.F) swap(a , b);
	 	 while (cur[i].size() > 0 && a.F > 0) {
	 		 c[cur[i].back() - 1] = a.S;
			 cur[i].pop_back();
			 --a.F;	
		 }
		 while (cur[i].size() > 0 && b.F > 0) {
		 	 c[cur[i].back() - 1] = b.S;
		 	 cur[i].pop_back();
		 	 --b.F;
		 } 
	 }
	 c[N] = ''; 
	 puts(c);
         return 0; 
}
原文地址:https://www.cnblogs.com/evenbao/p/14400819.html