zoukankan      html  css  js  c++  java
  • 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; 
    }
    
  • 相关阅读:
    【网络文摘】一位36岁程序员的困惑
    【网络文摘】大龄程序员怎样渡过中年危机?
    【问题与解决】showModalDialog is not defined 的解决方案
    【ASP.NET 问题】ASP.NET 网站404页面返回200,或者302的解决办法
    IIS 网站 HTTP 转 HTTPS
    ECharts JS应用:图表页面实现
    【问题与解决】怎么删除TFS云端上的项目
    【问题与解决】Github 上传代码报错(error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version)
    【问题与解决】Mac OS通过 npm 安装 React Native 报错(checkPermissions Missing write access to /usr/local/lib/node_modules)
    【JavaScript 插件】图片展示插件 PhotoSwipe 初识
  • 原文地址:https://www.cnblogs.com/evenbao/p/14400819.html
Copyright © 2011-2022 走看看