CodeforcesRound#550(Div. 3)(ABCDF题解)

http://codeforces.com/contest/1144/problem/A

题意:对于给定字符串,是否符合所有字母都只出现了一次并且排序后是连续的。

   比如 "adfceb" 就是合法的,"az" 和 "aab" 是不合法的。

思路:排序字符串后比较邻近的即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n,m,k;
 5 
 6 int main()
 7 {
 8     char in[105];
 9     int vis[105];
10     cin >> n;
11     while(n --){
12         memset(vis,0,sizeof(vis));
13         scanf("%s",in);
14         int L = strlen(in);
15         if(L == 1){cout << "YES" << endl;continue;}
16         for(int i = 0;i < L;i ++){
17             vis[i] = (int)(in[i] - 'a');
18         }
19         sort(vis,vis + L);
20         int a = vis[0];
21         int f = 0;
22         for(int i = 1;i < L;i ++){
23             if(vis[i] == a + 1){
24                 a ++;
25             }
26             else{f = 1;break;}
27         }
28         if(f){cout << "NO" << endl;}
29         else{cout << "YES" << endl;}
30     }
31 
32     return 0;
33 }
A

http://codeforces.com/contest/1144/problem/B

题意:对于给定数列,每次可以删掉一个某个数字,但是必须与上一个删去数字的奇偶性不同,否则无法删去。

   第一个删去的数字是任意的。无法继续删除后,统计数列的和作为答案,要求输出最小可能的答案。

思路:统计奇偶数字即可。排序后从小的贪心。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n,m,k;
 5 
 6 int main()
 7 {
 8     int a[2005];
 9     cin >> n;
10     int t1 = 0,t2 = 0;
11     for(int i = 0;i < n;i ++){
12         cin >> a[i];
13         if(a[i] % 2){t1 ++;}
14         else{t2 ++;}
15     }
16     if(abs(t1 - t2) <= 1){
17         cout << "0" << endl;
18         return 0;
19     }
20     sort(a,a + n);
21     if(t1 > t2){
22         int ans = 0;
23         int p = t1 - t2 - 1;
24         for(int i = 0;i < n;i ++){
25             if(!p){break;}
26             if(a[i] % 2){ans += a[i];p --;}
27         }
28         cout << ans << endl;
29     }
30     else{
31         int ans = 0;
32         int p = t2 - t1 - 1;
33         for(int i = 0;i < n;i ++){
34             if(!p){break;}
35             if(a[i] % 2 == 0){ans += a[i];p --;}
36         }
37         cout << ans << endl;
38     }
39 
40     return 0;
41 }
B

http://codeforces.com/contest/1144/problem/C

题意:对于给定数列,是否可以将其拆分成一个严格单调递增,一个严格单调递减序列。空序列也算是严格单调的。

思路:数列中不能出现多于两个的同种数,否则就是NO。

   对于合法数列,排序后按奇偶位置分成两个即可。

#include <bits/stdc++.h>
using namespace std;

int n,m,k;
int a[200005];
int a1[200005];
int a2[200005];
int vis[200005];
int main()
{
    int n;
    cin >> n;
    memset(vis,0,sizeof(vis));
    for(int i = 0;i < n;i ++){
        cin >> a[i];
        vis[a[i]] ++;
    }
    for(int i = 0;i <= 200000;i ++){
        if(vis[i] >= 3){
            cout << "NO" << endl;
            return 0;
        }
    }
    sort(a,a + n);
    int cnt1 = 0,cnt2 = 0;
    for(int i = 0;i < n;i ++){
        if(i % 2){a1[cnt1 ++] = a[i];}
        else{a2[cnt2 ++] = a[i];}
    }
    cout << "YES" << endl;
    cout << cnt1 << endl;
    for(int i = 0;i < cnt1;i ++){
        if(i != 0){cout << " ";}
        cout << a1[i];
    }cout << endl;
    cout << cnt2 << endl;
    for(int i = cnt2 - 1;i >= 0;i --){
        if(i != cnt2 - 1){cout << " ";}
        cout << a2[i];
    }cout << endl;

    return 0;
}
C

http://codeforces.com/contest/1144/problem/D

题意:对于给定数列,你可以对任意一个数字进行以下两种操作:

   1、将这个数字 a[i] 改成 a[i] + | a[i] - a[j] |,并且 | i - j | == 1,竖线是绝对值符号。

   2、将这个数字 a[i] 改成 a[i] -  | a[i] - a[j] |,并且 | i - j | == 1,竖线是绝对值符号。

   问你在最少多少次操作后,这个数列的所有数字都相等。题目保证所给数列可以变成要求的数列。

思路:明显最小操作数应该是数列长度减去数列中最多数字的数量,因为一定能转化成要求数列,所以对于任意两个相邻数,一定能将他们两个变为相等。

   所以只需要找到任意一个众数,然后向两边模拟即可。

   虽然题目不难,但还是错了好几发。。。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n,m,k;
 5 int a[200005];
 6 int vis[200005];
 7 int main()
 8 {
 9     int n;
10     cin >> n;
11     memset(vis,0,sizeof(vis));
12     int maxx = 0,s = 0;
13     for(int i = 1;i <= n;i ++){
14         cin >> a[i];
15         vis[a[i]] ++;
16         if(vis[a[i]] > maxx){
17             maxx = vis[a[i]];
18             s = a[i];
19         }
20     }
21     cout << n - maxx << endl;
22     int st = -1;
23     for(int i = 1;i <= n;i ++){
24         if(a[i] == s){st = i;break;}
25     }
26     for(int i = st - 1;i >= 1;i --){
27         if(a[i] < a[i + 1]){
28             printf("1 %d %d
",i,i + 1);
29         }
30         else if(a[i] > a[i + 1]){
31             printf("2 %d %d
",i,i + 1);
32         }
33         a[i] = a[i + 1];
34     }
35     for(int i = st + 1;i <= n;i ++){
36         if(a[i] < a[i - 1]){
37             printf("1 %d %d
",i,i - 1);
38         }
39         else if(a[i] > a[i - 1]){
40             printf("2 %d %d
",i,i - 1);
41         }
42         a[i] = a[i - 1];
43     }
44 
45     return 0;
46 }
D

http://codeforces.com/contest/1144/problem/F

题意:给你一个无向图,你要将所有的边都变成有向边,问是否存在一种策略,使得所有的点都只有入度或者出度。

思路:裸的图上搜索,依照题意模拟即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n,m,k;
 5 vector<int> V[200005];
 6 int vis[200005];
 7 int ans[200005];
 8 int flag = 0;
 9 struct Edge{
10     int f,t;
11 }e[200005];
12 
13 void dfs(int x){
14     vis[x] = 1;
15     for(int i = 0;i < V[x].size();i ++){
16         if(vis[V[x][i]] == 0){
17             ans[V[x][i]] = 3 - ans[x];
18             dfs(V[x][i]);
19         }
20         else{
21             if(ans[V[x][i]] == ans[x]){
22                 flag = 1;
23             }
24         }
25     }
26 }
27 
28 int main()
29 {
30     memset(vis,0,sizeof(vis));
31     memset(ans,-1,sizeof(ans));
32     int n,m;
33     cin >> n >> m;
34     for(int i = 1;i <= m;i ++){
35         cin >> e[i].f >> e[i].t;
36         V[e[i].f].push_back(e[i].t);
37         V[e[i].t].push_back(e[i].f);
38     }
39     ans[1] = 1;
40     dfs(1);
41     if(flag){cout << "NO" << endl;return 0;}
42     cout << "YES" << endl;
43     for(int i = 1;i <= m;i ++){
44         cout << (ans[e[i].f] - 1);
45     }
46 
47     return 0;
48 }
F
原文地址:https://www.cnblogs.com/love-fromAtoZ/p/10638830.html