namespace IO { /* 省略 */ } using IO::read; using IO::write;
#define lowbit(x) ((x)&(-x)) constint N = 100010, M = 200010; int n, k, ans[N]; structPoint { int x, y, z, s, res; booloperator==(const Point& p) const { return x == p.x && y == p.y && z == p.z; }
booloperator<(const Point& p) const { if (x != p.x) return x < p.x; if (y != p.y) return y < p.y; return z < p.z; } } p[N], tmp[N];
structBIT { int tr[M];
intquery(int p){ int res = 0; for (; p; p -= lowbit(p)) res += tr[p]; return res; }
voidadd(int p, int k){ for (; p < M; p += lowbit(p)) tr[p] += k; } } bit;
voidCDQ(int l, int r){ if (l >= r) return; int mid = (l+r) >> 1; CDQ(l, mid), CDQ(mid+1, r); int i = l, j = mid+1, cnt = 0; while (i <= mid && j <= r) { if (p[i].y <= p[j].y) bit.add(p[i].z, p[i].s), tmp[cnt++] = p[i++]; else p[j].res += bit.query(p[j].z), tmp[cnt++] = p[j++]; }
while (i <= mid) bit.add(p[i].z, p[i].s), tmp[cnt++] = p[i++]; while (j <= r) p[j].res += bit.query(p[j].z), tmp[cnt++] = p[j++];
for (i = l; i <= mid; i++) bit.add(p[i].z, -p[i].s); for (i = l; i <= r; i++) p[i] = tmp[i-l]; }
intmain(){ read(n, k); for (int i = 1; i <= n; i++) read(p[i].x, p[i].y, p[i].z); sort(p+1, p+1+n); int m = 0; for (int i = 1; i <= n; i++) { int ptr = i; while (p[ptr] == p[i]) p[i].s++, ptr++; p[++m] = p[i]; i = ptr-1; } CDQ(1, m); for (int i = 1; i <= m; i++) ans[p[i].res + p[i].s - 1] += p[i].s; for (int i = 0; i < n; i++) write(ans[i]); return0; }
[CQOI2017] 老C的任务
给定 n 个点,每个点 (x,y,p),再给 m 个查询,每次查询 (x1,y1)∼(x2,y2) 区域内所有点的 p 之和。
namespace IO { /* 省略 */ } using IO::read; using IO::write;
#define int long long constint N = 500010;
structPoint { int x, y, z, p, sgn, id; int res; booloperator<(const Point& d) const { if (x != d.x) return x < d.x; if (y != d.y) return y < d.y; return z < d.z; } } p[N], tmp[N];
int n, m, ans[N];
voidCDQ(int l, int r){ if (l >= r) return; int mid = (l+r) >> 1; CDQ(l, mid), CDQ(mid+1, r); int i = l, j = mid+1, cnt = 0, res = 0;
while (i <= mid && j <= r) { if (p[i].y <= p[j].y) res += p[i].p, tmp[cnt++] = p[i++]; else p[j].res += res, tmp[cnt++] = p[j++]; } while (i <= mid) tmp[cnt++] = p[i++]; while (j <= r) p[j].res += res, tmp[cnt++] = p[j++]; for (i = l; i <= r; i++) p[i] = tmp[i-l]; }
signedmain(){ read(n, m); for (int i = 0; i < n; i++) read(p[i].x, p[i].y, p[i].p); int k = n; for (int i = 0, x1, y1, x2, y2; i < m; i++) { read(x1, y1, x2, y2); p[k++] = {x2, y2, 1, 0, 1, i}; p[k++] = {x1-1, y1-1, 1, 0, 1, i}; p[k++] = {x2, y1-1, 1, 0, -1, i}; p[k++] = {x1-1, y2, 1, 0, -1, i}; } sort(p, p+k); CDQ(0, k-1); for (int i = 0; i < k; i++) if (p[i].z) ans[p[i].id] += p[i].res * p[i].sgn; for (int i = 0; i < m; i++) write(ans[i]); return0; }
namespace IO { /* 省略 */ } using IO::read; using IO::write;
structPoint { int x, y, z, s, res; } p[N], tmp[N];
structBIT { int tr[M];
intquery(int p, int res = 0){ p = min(p+1, M-1); if (p <= 0) return0; for (; p; p -= p&-p) res += tr[p]; return res; }
voidmodify(int p, int k){ if (!k) return; p++; for (; p < M; p += p&-p) tr[p] += k; } } bit;
voidCDQ(int l, int r, int k){ if (l >= r) return; int mid = (l+r) >> 1; CDQ(l, mid, k), CDQ(mid+1, r, k);
int i = l, j = mid+1, cnt = 0; while (i <= mid && j <= r) { if (p[i].y <= p[j].y) bit.modify(p[i].z, p[i].s), tmp[cnt++] = p[i++]; else p[j].res += bit.query(p[j].z) - bit.query(p[j].z-k-1), tmp[cnt++] = p[j++]; }
while (i <= mid) bit.modify(p[i].z, p[i].s), tmp[cnt++] = p[i++]; while (j <= r) p[j].res += bit.query(p[j].z) - bit.query(p[j].z-k-1), tmp[cnt++] = p[j++];
for (i = l; i <= mid; i++) bit.modify(p[i].z, -p[i].s); for (i = l; i <= r; i++) p[i] = tmp[i-l]; }
intmain(){ int T, n, m, k; read(T); while (T--) { read(n, m, k); vector<vector<char>> mat(n, vector<char>(m));
auto rotate = [&]() -> void { vector<vector<char>> res(m, vector<char>(n)); for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) res[j][n-i-1] = mat[i][j]; mat.swap(res); swap(n, m); };
int ans = 0; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) read(mat[i][j]); for (int i = 0; i < 4; i++) { if (i) rotate(); int cnt = 0; for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) p[cnt++] = {i, j, i+j, mat[i][j] == '#', 0}; CDQ(0, cnt-1, k); for (int i = 0; i < cnt; i++) ans = max(ans, p[i].res + p[i].s); } write(ans); }
return0; }
[模板] 四维 LIS
给定 n 个点 (ai,bi,ci,di),求出 LIS。1≤n≤5×104,1≤m≤109,m 是所有坐标的绝对值的最大值。
voidCDQ2(int l, int r){ if (l >= r) return; int mid = (l+r) >> 1; CDQ2(l, mid); for (int i = l; i <= r; i++) p[i].tb = i > mid; sort(p+l, p+r+1, cmpc); for (int i = l; i <= r; i++) { if (!p[i].ta && !p[i].tb) bit.update(p[i].d, p[i].res + p[i].s); if (p[i].ta && p[i].tb) p[i].res = max(p[i].res, bit.query(p[i].d)); } for (int i = l; i <= r; i++) { if (!p[i].ta && !p[i].tb) bit.clear(p[i].d); } sort(p+l, p+r+1, cmpb); CDQ2(mid+1, r); }
voidCDQ1(int l, int r){ if (l >= r) return; int mid = (l+r) >> 1; CDQ1(l, mid); for (int i = l; i <= r; i++) p[i].ta = i > mid; sort(p+l, p+r+1, cmpb); CDQ2(l, r); sort(p+l, p+r+1, cmpa); CDQ1(mid+1, r); }
vector<int> nums;
intmain(){ int n, ans = 0; read(n); nums.reserve(n); for (int i = 1; i <= n; i++) read(p[i].a, p[i].b, p[i].c, p[i].d), nums.emplace_back(p[i].d); sort(nums.begin(), nums.end()); for (int i = 1; i <= n; i++) p[i].d = lower_bound(nums.begin(), nums.end(), p[i].d) - nums.begin() + 1; sort(p+1, p+1+n, cmpa);
int m = 0; for (int i = 1; i <= n; i++) { int ptr = i; while (p[ptr] == p[i]) p[i].s++, ptr++; p[++m] = p[i]; i = ptr-1; } CDQ1(1, m); for (int i = 1; i <= m; i++) ans = max(ans, p[i].res + p[i].s); returnwrite(ans), 0; }