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 }

 

posted @ 2022-06-12 12:55  scannerkk  阅读(44)  评论(0)    收藏  举报