读题模拟即可
1 2 3 4 5 6 7 8 9 10 11 12 13 void solve () { int a1, a2, a4, a5; cin >> a1 >> a2 >> a4 >> a5; int x = a1 + a2, y = a4 - a2, z = a5 - a4; if (x == y && y == z) cout << 3 << endl; else if (x == y || y == z || x == z) cout << 2 << endl; else cout << 1 << endl; }
排序之后,出的每张牌都是有顺序的,只要扫描牌,都是 + 1 +1 + 1 单增,即代表可以打完
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 struct Cow { int n; vector<int > card; }; bool cmp (Cow a, Cow b) { return a.card[0 ] < b.card[0 ]; } void solve () { Cow cow[N]; cin >> n >> m; for (int i = 1 ; i <= n; i++) { cow[i].n = i; for (int j = 1 , x; j <= m; j++) { cin >> x; cow[i].card.push_back (x); } sort (cow[i].card.begin (), cow[i].card.end ()); } sort (cow + 1 , cow + n + 1 , cmp); int cnt = 0 ; for (int i = 1 ; i <= m; i++) { for (int j = 1 ; j <= n; j++) { if (cow[j].card[i - 1 ] == cnt) cnt++; else { cout << -1 << endl; return ; } } } for (int i = 1 ; i <= n; i++) cout << cow[i].n << " " ; cout << endl; }
成对的牌会抵消掉,数组要开大点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 void solve () { memset (cnt, 0 , sizeof cnt); cin >> n >> k; int maxx = 0 ; for (int i = 1 ; i <= n; i++) { int x; cin >> x, maxx = max (maxx, x), cnt[x]++; } int res = 0 ; for (int i = 1 ; i <= k; i++) { int x = cnt[i], y = cnt[k - i], t = 0 ; if (i == k - i) t = x / 2 , cnt[i] -= t; else t = min (x, y), cnt[i] -= t, cnt[k - i] -= t; res += t; } cout << res << endl; }
从第二个开始扫,全部都减掉,只要能扫完即代表数组可以操作成非递减
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void solve () { cin >> n; for (int i = 1 ; i <= n; i++) cin >> a[i]; int idx = 2 ; while (idx <= n) { int t = min (a[idx - 1 ], a[idx]); a[idx - 1 ] -= t, a[idx] -= t; if (a[idx] < a[idx - 1 ]) { cout << "NO" << endl; return ; } idx++; } cout << "YES" << endl; }
# 题目描述You are given two simple undirected graphs F F F and G G G with n n n vertices. F F F has m 1 m_1 m 1 edges while G G G has m 2 m_2 m 2 edges. You may perform one of the following two types of operations any number of times:
Select two integers u u u and v v v (1 ≤ u , v ≤ n 1 \leq u,v \leq n 1 ≤ u , v ≤ n ) such that there is an edge between u u u and v v v in F F F . Then, remove that edge from F F F . Select two integers u u u and v v v (1 ≤ u , v ≤ n 1 \leq u,v \leq n 1 ≤ u , v ≤ n ) such that there is no edge between u u u and v v v in F F F . Then, add an edge between u u u and v v v in F F F . Determine the minimum number of operations required such that for all integers u u u and v v v (1 ≤ u , v ≤ n 1 \leq u,v \leq n 1 ≤ u , v ≤ n ), there is a path from u u u to v v v in F F F if and only if there is a path from u u u to v v v in G G G .
# 题目解析这题大意是,给两个无向图:F , g i v e n F,~given F , g i v e n 。你可以进行两种操作
删除 F F F 的一条边 往 F F F 中添加一条边 问:要使得 G G G 中的任意连通的两个点,在 F F F 中也连通,最小需要多少次操作?
# 解析这题用到了 并查集 维护 两个点连通 ⇔ \Leftrightarrow ⇔ 在一个并查集内
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 int n, m1, m2, x, y, fa[N], fb[N];int find (int x, int f[]) { return x == f[x] ? x : f[x] = find (f[x], f); } int unite (int x, int y, int f[]) { int fx = find (x, f), fy = find (y, f); if (fx != fy) { f[fx] = fy; return 1 ; } return 0 ; } int isConnected (int x, int y, int f[]) { return find (x, f) == find (y, f); } void solve () { vector<PII> v; cin >> n >> m1 >> m2; for (int i = 1 ; i <= n; i++) fa[i] = fb[i] = i; int res = 0 , cnt1 = n, cnt2 = n; for (int i = 1 ; i <= m1; i++) cin >> x >> y, v.push_back ({x, y}); for (int i = 1 ; i <= m2; i++) cin >> x >> y, cnt2 -= unite (x, y, fb); for (auto side : v) { x = side.first, y = side.second; if (isConnected (x, y, fb) == 0 ) res++; else cnt1 -= unite (x, y, fa); } cout << res + cnt1 - cnt2 << endl; }