【LOJ2326】「清華集訓 2017」簡單資料結構
阿新 • • 發佈:2018-11-08
【題目連結】
【思路要點】
- 注意到答案是 級別的。
- 對於每一個點 我們暴力維護其 值 以及能夠轉移到 的各個位置的中 值為 的位置數 。
- 令 表示 的因子個數。
- 對於操作 ,其時間複雜度為 。
- 對於操作 ,其時間複雜度為 。
- 對於操作 ,其時間複雜度為 。
- 對於操作 ,其時間複雜度為 。
- 由於題目保證 ,總時間複雜度是可以接受的。
【程式碼】
#include<bits/stdc++.h> using namespace std; const int MAXLOG = 25; const int MAXN = 1e6 + 5; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, m, q, l, r, a[MAXN], ans[MAXLOG]; int pos[MAXN], dp[MAXN], cnt[MAXN][MAXLOG]; void answer() { for (int i = MAXLOG - 1; i >= 0; i--) if (ans[i]) { printf("%d %d\n", i, ans[i]); return; } assert(false); } void clear(int x) { memset(cnt[x], 0, sizeof(cnt[x])); dp[x] = 1, cnt[x][1] = 1; } void pushfront(int x) { clear(x); pos[x] = --l, a[l] = x; for (int i = 2 * x; i <= m; i += x) if (pos[i]) cnt[x][dp[i] + 1]++; for (int i = MAXLOG - 1; i >= 1; i--) if (cnt[x][i]) { dp[x] = i; break; } ans[dp[x]]++; } void popfront() { int x = a[l++]; ans[dp[x]]--, pos[x] = 0; } int val[MAXN], old[MAXN], tot; void update(int x, int val, int d) { ans[val] += d; for (int i = 1; i * i <= x; i++) if (x % i == 0) { if (pos[i] < pos[x]) cnt[i][val + 1] += d; if (i * i != x && pos[x / i] < pos[x]) cnt[x / i][val + 1] += d; } } void pushback(int x) { clear(x); pos[x] = ++r, a[r] = x; tot = 0; for (int i = 1; i * i <= x; i++) if (x % i == 0) { val[++tot] = i, old[i] = dp[i]; if (i * i != x) val[++tot] = x / i, old[x / i] = dp[x / i]; } sort(val + 1, val + tot + 1); update(x, dp[x], 1); for (int j = tot - 1; j >= 1; j--) { int x = val[j]; for (int i = MAXLOG - 1; i >= 1; i--) if (cnt[x][i]) { dp[x] = i; break; } if (!pos[x] || old[x] == dp[x]) continue; update(x, old[x], -1); update(x, dp[x], 1); } } void popback() { int x = a[r--]; tot = 0; for (int i = 1; i * i <= x; i++) if (x % i == 0) { val[++tot] = i, old[i] = dp[i]; if (i * i != x) val[++tot] = x / i, old[x / i] = dp[x / i]; } sort(val + 1, val + tot + 1); update(x, dp[x], -1); for (int j = tot - 1; j >= 1; j--) { int x = val[j]; for (int i = MAXLOG - 1; i >= 1; i--) if (cnt[x][i]) { dp[x] = i; break; } if (!pos[x] || old[x] == dp[x]) continue; update(x, old[x], -1); update(x, dp[x], 1); } pos[x] = 0; } int main() { read(n), read(m), read(q); l = 5e5, r = l - 1; for (int i = 1; i <= n; i++) { int x; read(x); pushback(x); } answer(); for (int i = 1; i <= q; i++) { int opt, x; read(opt); if (opt <= 1) { read(x); if (opt == 0) pushfront(x); else pushback(x); } else { if (opt == 2) popfront(); else popback(); } answer(); } return 0; }