Codeforces Round #656 (Div. 3)题解

A.Three Pairwise Maximums

解题思路:

依照题意和样例,三个整数x,y,z必须有两个相同且都比第三个数大。
如果x==y则说明a为最大值,此时需要满足a>=z,如果不满足该条件,则无解,因为z=max(b,c),我们不能确定b,c谁比较大,所以我们就假设两个数一样的即可。而当y == z和x == z同理。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int a[3];
  4. int main() {
  5. //freopen("in.txt", "r", stdin);
  6. ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  7. int t; cin >> t; while (t--) {
  8. cin >> a[0] >> a[1] >> a[2];
  9. sort(a, a + 3);
  10. if (a[1] != a[2]) {
  11. cout << "NO" << endl;
  12. continue;
  13. }
  14. cout << "YES" << endl;
  15. cout << a[0] << " " << a[0] << " " << a[2] << endl;
  16. }
  17. }

B.Restore the Permutation by Merger

题目说是相对顺序插入的,所以我们可以直接遍历来做。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int t, n, a;
  4. int main() {
  5. //freopen("in.txt", "r", stdin);
  6. ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  7. cin >> t; while (t--) {
  8. cin >> n; int b[55] = { 0 };
  9. for (int i = 0; i < 2 * n; ++i) {
  10. cin >> a;
  11. if (!b[a])
  12. cout << a << " ";
  13. b[a]++;
  14. }
  15. cout << endl;
  16. }
  17. }

C.Make It Good

解题思路:
满足中间大两边小。
要找最长“好序列”,从后往前找,找到第一个不满足从后往前递增条件的元素,然后从这个元素往前找,找到开始升的那个元素就停止。最后答案就是n减去最长“好序列”长度。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int a[200005];
  4. int main()
  5. {
  6. int t;
  7. cin >> t;
  8. while (t--)
  9. {
  10. int n;
  11. cin >> n;
  12. for (int i = 1; i <= n; i++) cin >> a[i];
  13. int R = n;
  14. while (a[R - 1] >= a[R] && R >= 1) R--;
  15. while (a[R - 1] <= a[R] && R >= 1) R--;
  16. int ans = R - 1;
  17. if (ans == -1) ans = 0;
  18. cout << ans << endl;
  19. }
  20. return 0;
  21. }

D. a-Good String

解题思路:
暴力枚举,取最小值

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. char a[131073];
  4. int t, n;
  5. int solve(int l,int r,char m) {
  6. if (l == r) {
  7. if (a[l] == m)return 0;
  8. else return 1;
  9. }
  10. int mid = (l + r) >> 1, left = 0, right = 0,len = r - l + 1;
  11. for (int i = l; i <= mid; ++i) if (a[i] == m)left++;
  12. for (int i = mid + 1; i <= r; ++i) if (a[i] == m)right++;
  13. int ans = min(len / 2 - left + solve(mid + 1, r, m + 1), len / 2 - right + solve(l, mid, m + 1));
  14. return ans;
  15. }
  16. int main() {
  17. //freopen("in.txt", "r", stdin);
  18. ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  19. cin >> t; while (t--) {
  20. char m = 'a';
  21. cin >> n;for(int i = 1;i <= n;++i){
  22. cin >> a[i];
  23. }
  24. cout << solve(1, n, m) << endl;
  25. }
  26. }

E. Directing Edges

解题思路:
首先可以看出这是一道拓扑的题。但由于不太好维护得建图。建反方向的边,最后再拓扑排。但由于我太菜了,就没做出来。代码就放dalao们做的了。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. vector<int>e[200005];
  4. int u[200005],v[200005];
  5. int T,n,m;
  6. int in[200005],tp[200005];
  7. queue<int>q;
  8. bool topsort(){
  9. int ct=0,tmp=0;
  10. for(int i=1;i<=n;i++) if(!in[i]) q.push(i),ct++,tp[i]=++tmp;
  11. while(!q.empty()){
  12. int U=q.front();q.pop();
  13. for(int V:e[U]){
  14. in[V]--;
  15. if(!in[V]) q.push(V),ct++,tp[V]=++tmp;
  16. }
  17. }
  18. return ct<n;
  19. }
  20. int main(){
  21. scanf("%d",&T);
  22. while(T--){
  23. scanf("%d%d",&n,&m);memset(in,0,sizeof(in));
  24. for(int i=1;i<=n;i++) e[i].clear();
  25. for(int o,i=1;i<=m;i++){
  26. scanf("%d%d%d",&o,&u[i],&v[i]);
  27. if(o) in[v[i]]++,e[u[i]].emplace_back(v[i]);
  28. }if(topsort()) puts("NO");
  29. else{
  30. puts("YES");
  31. for(int i=1;i<=m;i++)
  32. if(tp[u[i]]<tp[v[i]]) printf("%d %d\n",u[i],v[i]);
  33. else printf("%d %d\n",v[i],u[i]);
  34. }
  35. }return 0;
  36. }