【题目链接】
【思路要点】
- 树套树,KDTree,CDQ分治都能做。
- CDQ分治的话需要注意这里要求“严格小于”,取中点时应当保证左右两边第一维坐标不会相等。
- 时间复杂度\(O(NLog^2N)\)或\(O(N\sqrt{N})\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 100005; 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(""); } struct BinaryIndexTree { int n, a[MAXN * 3]; void init(int x) { n = x; memset(a, 0, sizeof(a)); } void modify(int pos, int val) { for (int i = pos; i <= n; i += i & -i) chkmax(a[i], val); } void clear(int pos) { for (int i = pos; i <= n; i += i & -i) a[i] = 0; } int query(int pos) { int ans = 0; for (int i = pos; i >= 1; i -= i & -i) chkmax(ans, a[i]); return ans; } } BIT; struct info {int x, y, z, dp; }; int n, P, x; int tot, tmp[MAXN * 3]; int pre[MAXN], suf[MAXN]; info a[MAXN]; bool cmpz(info a, info b) {return a.z < b.z; } bool cmpx(info a, info b) {return a.x < b.x; } void work(int l, int r) { if (a[l].z == a[r].z) return; int mid = (l + r) / 2; if (pre[mid] == l) mid = suf[mid]; else mid = pre[mid] - 1; work(l, mid); sort(a + l, a + mid + 1, cmpx); sort(a + mid + 1, a + r + 1, cmpx); int pos = l; for (int i = mid + 1; i <= r; i++) { while (pos <= mid && a[i].x > a[pos].x) BIT.modify(a[pos].y, a[pos].dp), pos++; chkmax(a[i].dp, 1 + BIT.query(a[i].y - 1)); } for (int i = l; i < pos; i++) BIT.clear(a[i].y); sort(a + mid + 1, a + r + 1, cmpz); work(mid + 1, r); } int main() { read(x), read(P), read(n); int now = 1; for (int i = 1; i <= n; i++) { now = now * x % P; a[i].x = now; tmp[++tot] = now; now = now * x % P; a[i].y = now; tmp[++tot] = now; now = now * x % P; a[i].z = now; tmp[++tot] = now; a[i].dp = 1; if (a[i].x > a[i].y) swap(a[i].x, a[i].y); if (a[i].y > a[i].z) swap(a[i].y, a[i].z); if (a[i].x > a[i].y) swap(a[i].x, a[i].y); } sort(tmp + 1, tmp + tot + 1); tot = unique(tmp + 1, tmp + tot + 1) - tmp - 1; for (int i = 1; i <= n; i++) { a[i].x = lower_bound(tmp + 1, tmp + tot + 1, a[i].x) - tmp; a[i].y = lower_bound(tmp + 1, tmp + tot + 1, a[i].y) - tmp; a[i].z = lower_bound(tmp + 1, tmp + tot + 1, a[i].z) - tmp; } sort(a + 1, a + n + 1, cmpz); for (int i = 1; i <= n; i++) if (a[i].z == a[i - 1].z) pre[i] = pre[i - 1]; else pre[i] = i; for (int i = n; i >= 1; i--) if (a[i].z == a[i + 1].z) suf[i] = suf[i + 1]; else suf[i] = i; BIT.init(tot); work(1, n); int ans = 0; for (int i = 1; i <= n; i++) chkmax(ans, a[i].dp); writeln(ans); return 0; }