CF798div2A-C题解
一.A
1.题意:给定你两个字符串,每次从一个字符串里面选取一个字符放到c串的末尾,不可以对每一个字符串连续操作k次,直到某一个取完后,这个追加操作就停止。现在问你,构成的c串最小字典序是多少
2.题解这个题根据贪心的策略,我们每次选择 一个两个字符串中间的最小的那个字符,如果该串已经操作了k次,那么就必须选择另一个串的字符。
3.代码实现:
1 // Problem: A. Lex String 2 // Contest: Codeforces - Codeforces Round #798 (Div. 2) 3 // URL: https://codeforces.com/contest/1689/problem/0 4 // Memory Limit: 256 MB 5 // Time Limit: 1000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 #include <iostream> 10 #include <queue> 11 #include <vector> 12 #include <cstring> 13 #include <string> 14 #include <map> 15 #include <cmath> 16 #include <algorithm> 17 #include <set> 18 #include <stack> 19 #include <cstdio> 20 #include <climits> 21 #define PII pair<int,int> 22 #define rep(i,z,n) for(int i = z;i <= n; i++) 23 #define per(i,n,z) for(int i = n;i >= z; i--) 24 #define ll long long 25 #define db double 26 #define vi vector<int> 27 #define debug(x) cerr << "!!!" << x << endl; 28 using namespace std; 29 inline ll rd() 30 { 31 ll s,r; 32 r = 1; 33 s = 0; 34 char ch = getchar(); 35 while(ch < '0' || ch > '9'){ 36 if(ch == '-') 37 r = -1; 38 ch = getchar(); 39 } 40 while(ch >= '0' && ch <= '9'){ 41 s = (s << 1) + (s << 3) + (ch ^ 48); 42 ch = getchar(); 43 } 44 return s * r; 45 } 46 inline void wt(ll x) 47 { 48 if(x < 0) putchar('-'),x = -x; 49 if(x > 9) wt(x / 10); 50 putchar(x % 10 + '0'); 51 } 52 ll gcd(ll a,ll b) 53 { 54 if(!b) return a; 55 else return gcd(b,a%b); 56 } 57 ll lcm(ll a,ll b) 58 { 59 return a*b/gcd(a,b); 60 } 61 char s2[110],s3[110]; 62 bool cmp(char c,char d) 63 { 64 return c < d; 65 } 66 void solve() 67 { 68 int a,b,k; 69 cin >> a >> b >> k; 70 cin >> s2 >> s3; 71 sort(s2,s2+a,cmp); 72 sort(s3,s3+b,cmp); 73 int l1,l2; 74 l1=l2=0; 75 int cnta,cntb; 76 cnta=cntb=0; 77 string ans=""; 78 while(l1<a&&l2<b){ 79 if(s2[l1]<s3[l2]){ 80 if(cnta>=k){ 81 ans+=s3[l2]; 82 l2++; 83 cnta=0; 84 cntb=1; 85 continue; 86 } 87 ans+=s2[l1]; 88 cntb=0; 89 cnta++; 90 l1++; 91 } 92 else { 93 if(cntb>=k){ 94 ans+=s2[l1]; 95 l1++; 96 cntb=0; 97 cnta=1; 98 continue; 99 } 100 ans+=s3[l2]; 101 cnta=0; 102 cntb++; 103 l2++; 104 } 105 // cout<<ans<<endl; 106 } 107 cout<<ans<<endl; 108 } 109 int main() 110 { 111 int t; 112 cin >> t; 113 while(t--){ 114 solve(); 115 } 116 return 0; 117 }
二.B
1.题意:给定你一个数组,问你在不与原来位置相同的位置上放置相同的数的情况下,构成一个字典序最小的数组
2.题解:对于每一个数位,我们尽可能的去寻找小的数,但是最后两位是特殊的。
(1)考虑最后两位相同的情况,如果最后两个都与原位置冲突,就交换两个
(2)考虑最后两位只有个位相同的情况,交换两个位置,因为如果这两个中只有一个相同,那么其他n-2个中肯定有一个拿了其中一个的位置,交换过后则不会造成答案不符。
3.代码实现:
1 // Problem: B. Mystic Permutation 2 // Contest: Codeforces - Codeforces Round #798 (Div. 2) 3 // URL: https://codeforces.com/contest/1689/problem/B 4 // Memory Limit: 256 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 #include <iostream> 10 #include <queue> 11 #include <vector> 12 #include <cstring> 13 #include <string> 14 #include <map> 15 #include <cmath> 16 #include <algorithm> 17 #include <set> 18 #include <stack> 19 #include <cstdio> 20 #include <climits> 21 #define PII pair<int,int> 22 #define rep(i,z,n) for(int i = z;i <= n; i++) 23 #define per(i,n,z) for(int i = n;i >= z; i--) 24 #define ll long long 25 #define db double 26 #define vi vector<int> 27 #define debug(x) cerr << "!!!" << x << endl; 28 using namespace std; 29 inline ll rd() 30 { 31 ll s,r; 32 r = 1; 33 s = 0; 34 char ch = getchar(); 35 while(ch < '0' || ch > '9'){ 36 if(ch == '-') 37 r = -1; 38 ch = getchar(); 39 } 40 while(ch >= '0' && ch <= '9'){ 41 s = (s << 1) + (s << 3) + (ch ^ 48); 42 ch = getchar(); 43 } 44 return s * r; 45 } 46 inline void wt(ll x) 47 { 48 if(x < 0) putchar('-'),x = -x; 49 if(x > 9) wt(x / 10); 50 putchar(x % 10 + '0'); 51 } 52 ll gcd(ll a,ll b) 53 { 54 if(!b) return a; 55 else return gcd(b,a%b); 56 } 57 ll lcm(ll a,ll b) 58 { 59 return a*b/gcd(a,b); 60 } 61 int a[1010],b[1010],cnt[1010],use[1010]; 62 void solve() 63 { 64 int n; 65 n = rd(); 66 memset(use,0,sizeof(use)); 67 for(int i=1;i<=n;i++) a[i]=rd(); 68 if(n==1){ 69 cout<<"-1"<<endl; 70 return ; 71 } 72 int z=1; 73 for(int i = 1;i <= n-2;i++){ 74 for(int j = 1;j <= n;j++){ 75 if(!use[j] && j != a[i]){ 76 b[i]=j; 77 use[j]=1; 78 break; 79 } 80 } 81 } 82 z=n-1; 83 for(int i = 1;i <= n;i++) if(!use[i]) b[z++]=i; 84 if(b[n-1]==a[n-1]||b[n]==a[n]) swap(b[n-1],b[n]); 85 for(int i = 1;i <= n;i++) cout<<b[i]<<' '; 86 cout<<endl; 87 } 88 int main() 89 { 90 int t; 91 t = rd(); 92 while(t--){ 93 solve(); 94 } 95 return 0; 96 }
三.C
1.题意:给定你一棵树,感染的节点为1,每次都可能感染他的边,你能做的操作是把未感染的节点删除掉,然后拯救未感染节点的儿子们,先问你能拯救的最大的儿子数为多少?
2.题解:对于每一次感染,如果这个未被感染的节点有一个子儿子,那么最好的操作就是切断这个节点,如果有两个,那我们则优先选择节点最多的那个。因此我们定义dp【i】为i被感染还能能拯救多少儿子,sz【i】为i节点的儿子的个数。
(1)当当前节点的孩子数只为1,很明显dp【i】= sz【i】- 1;
(2)当当前节点的孩子数只为2,很明显dp【i】= max(dp【child[0]】+ sz【child[1]】- 1,dp【child[1]】+ sz【child[0]】- 1);
3.代码实现
1 // Problem: C. Infected Tree 2 // Contest: Codeforces - Codeforces Round #798 (Div. 2) 3 // URL: https://codeforces.com/contest/1689/problem/C 4 // Memory Limit: 256 MB 5 // Time Limit: 3000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 #include <iostream> 10 #include <queue> 11 #include <vector> 12 #include <cstring> 13 #include <string> 14 #include <map> 15 #include <cmath> 16 #include <algorithm> 17 #include <set> 18 #include <stack> 19 #include <cstdio> 20 #include <climits> 21 #define PII pair<int,int> 22 #define rep(i,z,n) for(int i = z;i <= n; i++) 23 #define per(i,n,z) for(int i = n;i >= z; i--) 24 #define ll long long 25 #define db double 26 #define vi vector<int> 27 #define debug(x) cerr << "!!!" << x << endl; 28 using namespace std; 29 inline ll rd() 30 { 31 ll s,r; 32 r = 1; 33 s = 0; 34 char ch = getchar(); 35 while(ch < '0' || ch > '9'){ 36 if(ch == '-') 37 r = -1; 38 ch = getchar(); 39 } 40 while(ch >= '0' && ch <= '9'){ 41 s = (s << 1) + (s << 3) + (ch ^ 48); 42 ch = getchar(); 43 } 44 return s * r; 45 } 46 inline void wt(ll x) 47 { 48 if(x < 0) putchar('-'),x = -x; 49 if(x > 9) wt(x / 10); 50 putchar(x % 10 + '0'); 51 } 52 ll gcd(ll a,ll b) 53 { 54 if(!b) return a; 55 else return gcd(b,a%b); 56 } 57 ll lcm(ll a,ll b) 58 { 59 return a*b/gcd(a,b); 60 } 61 vector<int> E[300010]; 62 int sz[300010],pre[300010],dp[300010]; 63 void dfs(int u) 64 { 65 sz[u]=1; 66 vector<int> child; 67 for(auto x:E[u]){ 68 if(x==pre[u]) continue; 69 pre[x]=u; 70 dfs(x); 71 child.push_back(x); 72 sz[u]+=sz[x]; 73 } 74 if(child.size()==1) dp[u]=sz[child[0]]-1; 75 if(child.size()==2) dp[u]=max(dp[child[0]] + sz[child[1]]-1,dp[child[1]] + sz[child[0]]-1); 76 } 77 void solve() 78 { 79 ll n,u,v; 80 n = rd(); 81 for(int i = 1;i <= n;i++) dp[i]=0,pre[i]=0,sz[i]=0,E[i].clear(); 82 for(int i = 1;i <= n-1;i++){ 83 u = rd(),v = rd(); 84 E[u].push_back(v); 85 E[v].push_back(u); 86 } 87 dfs(1); 88 wt((dp[1])); 89 puts(""); 90 } 91 int main() 92 { 93 int t; 94 t = rd(); 95 while(t--){ 96 solve(); 97 } 98 return 0; 99 }
本文来自博客园,作者:{scanner},转载请注明原文链接:{https://home.cnblogs.com/u/scannerkk/}