比赛链接:Here

1549A. Gregor and Cryptography

不难,观察一下就容易得知要想使得 Codeforces Round #736 (Div. 2) A~D - 图1Codeforces Round #736 (Div. 2) A~D - 图2 即可。

1549B. Gregor and the Pawn Game

一开始想叉了,直接贪心就可以

  1. const int N = 2e5 + 10;
  2. char s[N], s1[N];
  3. int main() {
  4. // cin.tie(nullptr)->sync_with_stdio(false);
  5. int _; for (cin >> _; _--;) {
  6. int n; cin >> n;
  7. scanf("%s%s", s + 1, s1 + 1);
  8. int ans = 0;
  9. for (int i = 1; i <= n; ++i) {
  10. if (s1[i] == '0') continue;
  11. if (s[i - 1] == '1') s[i - 1] = '2', ans++;
  12. else if (s[i] == '0') s[i] = '2', ans++;
  13. else if (s[i + 1] == '1') s[i + 1] = '2', ans++;
  14. }
  15. cout << ans << "\n";
  16. }
  17. }

1549C. Web of Lies

看过权游的话大概很快就理解题意了(笑

如果一个贵族至少有一个朋友,并且他的朋友都拥有更高的权利时他就会被杀害

给定 Codeforces Round #736 (Div. 2) A~D - 图3 种操作:

  1. 增加贵族 Codeforces Round #736 (Div. 2) A~D - 图4Codeforces Round #736 (Div. 2) A~D - 图5 的友谊

  2. 减少贵族 Codeforces Round #736 (Div. 2) A~D - 图6Codeforces Round #736 (Div. 2) A~D - 图7 的友谊

  3. 计算以下过程的答案。
    过程:所有易受伤害的贵族同时被杀害,他们的友谊也随之结束。这样,新贵族就有可能变得脆弱。这个过程不断重复,直到没有贵族受到伤害。可以证明,这个过程将在有限的时间内结束。完成此过程后,您需要计算剩余贵族的数量。

看完题,感觉是并查集,不过模拟时发现就是一个 拓扑排序了,输出的答案也是当前 Codeforces Round #736 (Div. 2) A~D - 图8 的个数

理解到是这个方面以后代码就很好写了

  1. const int N = 2e5 + 10;
  2. int deg[N];
  3. void solve() {
  4. int n, m; cin >> n >> m;
  5. for (int i = 1, x, y; i <= m; ++i) {
  6. cin >> x >> y;
  7. if (x > y) swap(x, y);
  8. deg[x]++;
  9. }
  10. int ans = 0;
  11. for (int i = 1; i <= n; ++i) if (deg[i] == 0) ans ++;
  12. int q; cin >> q;
  13. while (q--) {
  14. int op, x, y; cin >> op;
  15. if (op == 1) {
  16. cin >> x >> y;
  17. if (x > y) swap(x, y);
  18. deg[x]++;
  19. if (deg[x] == 1)ans--;
  20. } else if (op == 2) {
  21. cin >> x >> y;
  22. if (x > y) swap(x, y);
  23. deg[x]--;
  24. if (deg[x] == 0)ans++;
  25. } else cout << ans << "\n";
  26. }
  27. }

1549D.Integers Have Friends

不太会,赛后看了一下社区的解释

这道题的关键在于构建一个大小为 Codeforces Round #736 (Div. 2) A~D - 图9 的差分数组 Codeforces Round #736 (Div. 2) A~D - 图10Codeforces Round #736 (Div. 2) A~D - 图11#card=math&code=D%5Bi%5D%20%3D%20abs%28a%5Bi%20%2B%201%5D%20-%20a%5Bi%5D%29)

同时如果给定的数组子序列是一个友元序列,每个差就是某个 Codeforces Round #736 (Div. 2) A~D - 图12 的倍数(因为 Codeforces Round #736 (Div. 2) A~D - 图13 数组每个元素值都不同,所以可以不用管 Codeforces Round #736 (Div. 2) A~D - 图14 的情况)

然后针对上面的结论,可以将其转化为 GCD 问题,当且仅当 Codeforces Round #736 (Div. 2) A~D - 图15 时,Codeforces Round #736 (Div. 2) A~D - 图16 为友元序列 .

为了解决这个问题,我们可以使用一个稀疏表或一个段树来查找从i开始的最大可能子数组,然后对所有子数组的答案进行最大化以得到最终答案。

【Code】

  1. const int N = 2e5 + 10, LG = 17;
  2. ll a[N], st[N][18], lg[N];
  3. ll gcd(ll a, ll b) {
  4. if (b == 0)return a;
  5. else return gcd(b, a % b);
  6. }
  7. ll query(int l, int r) {
  8. int c = lg[r - l + 1];
  9. return gcd(st[l][c], st[r - (1 << c) + 1][c]);
  10. }
  11. int main() {
  12. cin.tie(nullptr)->sync_with_stdio(false);
  13. int _; for (cin >> _; _--;) {
  14. int n; cin >> n;
  15. for (int i = 1; i <= n; i++) cin >> a[i];
  16. for (int i = 1; i < n; i++)a[i] = abs(a[i + 1] - a[i]); n--;
  17. for (int i = 1; i <= n; i++)st[i][0] = a[i];
  18. for (int j = 1; j <= LG; j++)
  19. for (int i = 1; i <= n - (1 << j) + 1; i++)
  20. st[i][j] = gcd(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
  21. lg[1] = 0; for (int i = 2; i <= n; i++)lg[i] = lg[i >> 1] + 1;
  22. int l = 1, ans = 0;
  23. for (int r = 1; r <= n; r++) {
  24. while (l <= r && query(l, r) == 1)l++;
  25. ans = max(ans, r - l + 1);
  26. }
  27. cout << ans + 1 << "\n";
  28. }
  29. }
  1. const int inf = 1e9+10;
  2. const ll inf_ll = 1e18+10;
  3. #define all(x) (x).begin(), (x).end()
  4. #define pb push_back
  5. #define cmax(x, y) (x = max(x, y))
  6. #define cmin(x, y) (x = min(x, y))
  7. template<typename it, typename bin_op>
  8. struct sparse_table {
  9. using T = typename remove_reference<decltype(*declval<it>())>::type;
  10. vector<vector<T>> t; bin_op f;
  11. sparse_table(it first, it last, bin_op op) : t(1), f(op) {
  12. int n = distance(first, last);
  13. t.assign(32-__builtin_clz(n), vector<T>(n));
  14. t[0].assign(first, last);
  15. for (int i = 1; i < t.size(); i++)
  16. for (int j = 0; j < n-(1<<i)+1; j++)
  17. t[i][j] = f(t[i-1][j], t[i-1][j+(1<<(i-1))]);
  18. }
  19. // returns f(a[l..r]) in O(1) time
  20. T query(int l, int r) {
  21. int h = floor(log2(r-l+1));
  22. return f(t[h][l], t[h][r-(1<<h)+1]);
  23. }
  24. };
  25. int main() {
  26. ios_base::sync_with_stdio(0); cin.tie(0);
  27. int t; cin >> t;
  28. while (t--) {
  29. ll n; cin >> n;
  30. vector<ll> a(n), d(n-1);
  31. for (int i = 0; i < n; i++)
  32. cin >> a[i];
  33. for (int i = 0; i < n-1; i++)
  34. d[i] = abs(a[i+1]-a[i]);
  35. sparse_table g(all(d), [](ll x, ll y){
  36. return __gcd(x, y);
  37. });
  38. int j = 0, ans = 1;
  39. for (int i = 0; i < n-1; i++) {
  40. while (j <= i && g.query(j, i) == 1) j++;
  41. cmax(ans, i-j+2);
  42. }
  43. cout << ans << "\n";
  44. }
  45. }