codeforces round#600
A.
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e5 + 10; 4 int a[maxn], b[maxn]; 5 6 int main() 7 { 8 int t; cin >> t; 9 int n; 10 while (t--) 11 { 12 cin >> n; 13 for (int i = 1; i <= n; i++) 14 scanf("%d", a + i); 15 for (int i = 1; i <= n; i++) 16 scanf("%d", b + i); 17 int l = 1, r = n; 18 for (; l <= n && a[l] == b[l]; l++); 19 for (; r >= 1 && a[r] == b[r]; r--); 20 if (r < l) 21 printf("YES\n"); 22 else 23 { 24 int dif = b[l] - a[l]; 25 int flag = 0; 26 for(int i = l; i <= r; i++) 27 if (b[i] - a[i] != dif) 28 { 29 flag = 1; 30 break; 31 } 32 if (dif < 0 || flag) 33 printf("NO\n"); 34 else printf("YES\n"); 35 } 36 } 37 }
B.
分析:room表示公司当前包含的人,map表示每个人的状态:0 - 从来没进过公司, 1 - 进入了公司, 2 - 离开了公司(通过合法性检查保证不会出现进出多次的情况)
每当room为空,一天结束。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e5 + 10; 5 map<int, int> state; 6 set<int> room; 7 vector<int> res; 8 int n; 9 int v[maxn]; 10 11 int main() 12 { 13 cin >> n; 14 for (int i = 1; i <= n; i++) 15 scanf("%d", v + i); 16 int flag = 0; 17 for (int i = 1; i <= n; i++) 18 { 19 if (v[i] > 0) 20 { 21 if (!state.count(v[i])) 22 state[v[i]] = 1, room.insert(v[i]); 23 else { flag = 1; break; } 24 } 25 else 26 { 27 if (state.count(-v[i]) && state[-v[i]] == 1) 28 state[-v[i]] = 2, room.erase(-v[i]); 29 else { flag = 1; break; } 30 } 31 if (room.empty()) 32 { 33 res.push_back(state.size() * 2); 34 state.clear(); 35 } 36 } 37 if (flag) 38 cout << -1 << endl; 39 else 40 { 41 if (!room.empty()) 42 cout << -1 << endl; 43 else 44 { 45 cout << res.size() << endl; 46 for (int i = 0; i < res.size(); i++) 47 printf("%d%c", res[i], i == res.size() - 1 ? '\n' : ' '); 48 } 49 } 50 51 }
C.
分析:(先排序)暴力肯定t。需要找规律:各个输出的差 = 前k项间隔m项和(ak + a(k - m) + a(k - 2 * m) + ...)
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 2 * 1e5 + 10; 5 int v[maxn]; 6 ll sum[maxn]; 7 8 int main() 9 { 10 int n, m; cin >> n >> m; 11 for (int i = 1; i <= n; i++) 12 scanf("%d", v + i); 13 sort(v + 1, v + 1 + n); 14 for (int i = 1; i <= m; i++) 15 sum[i] = v[i]; 16 for (int i = m + 1; i <= n; i++) 17 sum[i] = sum[i - m] + v[i]; 18 ll res = 0; 19 for (int i = 1; i <= n; i++) 20 printf("%lld%c", res += sum[i], i == n ? '\n' : ' '); 21 }
D.
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 2 * 1e5 + 10; 4 int fa[maxn]; 5 int res = 0; 6 7 int find(int x) 8 { 9 return x == fa[x] ? x : fa[x] = find(fa[x]); 10 } 11 12 int main() 13 { 14 int n, m; cin >> n >> m; 15 for (int i = 1; i <= n; i++) 16 fa[i] = i; 17 for (int i = 1; i <= m; i++) 18 { 19 int x, y; 20 scanf("%d%d", &x, &y); 21 int fx = find(x), fy = find(y); 22 if (fx > fy) swap(fx, fy); 23 fa[fx] = fy; 24 } 25 for (int i = 1; i <= n; ) 26 { 27 int f = find(i); 28 int fx; 29 for(int j = i + 1; j <= f; j++) 30 if ((fx = find(j)) != f) 31 { 32 if (f < fx) fa[f] = fx, f = fx; 33 else fa[fx] = f; 34 res++; 35 } 36 i = f + 1; 37 } 38 cout << res << endl; 39 }
分析:并查集
对于每个连通分支,选最大的节点为父节点。然后从1开始遍历节点,对于当年节点i,检查从 i + 1 到 fa[i]的每个点(记为j),看是否从i可达,不可达的话,union(fa[i], fa[j])(大的做父亲).完成对i的检查之后,i = fa[i] + 1,检查剩余节点。