本篇主刷题
分治求最近点对距离
#include<iostream>#include<cmath>#include<algorithm>usingnamespacestd;
constint N = 1e5 + 7;
constdouble EPS = 1e-6;
double MX;
structPoint {double x, y;
bool type;
booloperator<(const Point &B) {
return x < B.x;
}
doubleoperator-(const Point &B) {
if (type == B.type) return MX;
double dx = x - B.x, dy = y - B.y;
returnsqrt(dx*dx + dy*dy);
}
} pt[N<<1];
doublecalc(int l, int r){
if (r-l < 2) return MX;
if (r-l == 2) return pt[l] - pt[l+1];
int mid = l + r >> 1;
double ans = MX = min(calc(l, mid), calc(mid+1, r));
for (int i = mid; i >= l; --i) {
if (pt[mid].x - pt[i].x > ans + EPS) break;
for (int j = mid+1; j <= r; ++j) {
if (pt[j].x - pt[i].x > ans + EPS) break;
ans = MX = min(ans, pt[i]-pt[j]);
}
}
return ans;
}
intmain(){
int T, n;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%lf%lf", &pt[i].x, &pt[i].y);
for (int i = 1; i <= n; ++i) {
scanf("%lf%lf", &pt[n+i].x, &pt[n+i].y);
pt[i].type = true;
}
sort(pt+1, pt+n+n+1);
MX = pt[1] - pt[n<<1];
printf("%.3f\n", calc(1, n<<1));
}
return0;
}
整体二分
#include<iostream>constint N = 3e5 + 7;
using LL = longlong;
LL s[N<<1];
int n, m, k;
int hd[N], nx[N], L[N], R[N], a[N], ans[N];
structState {int id, w;
} st[N<<1], _st[N<<1];
voidadd(int x, int v){
while (x <= m<<1)
s[x] += v, x += x&-x;
}
LL query(int x){
LL ans = 0;
while (x) ans += s[x], x &= x-1;
return ans;
}
voidsolve(int l, int r, int x, int y){
if (l == r) {
for (int i = x; i <= y; ++i) ans[st[i].id] = l;
return;
}
int mid = (l + r) >> 1, lo = 0, hi = n;
for (int i = l; i <= mid; ++i) add(L[i], a[i]), add(R[i]+1, -a[i]);
for (int i = x; i <= y; ++i) {
LL t = 0;
for (int j = hd[st[i].id]; j && t<=st[i].w; j = nx[j])
t += query(j+m) + query(j);
if (t >= st[i].w) _st[++lo] = st[i];
else _st[++hi] = st[i], _st[hi].w -= t;
}
for (int i = l; i <= mid; ++i) add(L[i], -a[i]), add(R[i]+1, a[i]);
for (int i = 1; i <= lo; ++i) st[x+i-1] = _st[i];
for (int i = n+1; i <= hi; ++i) st[x+lo+i-n-1] = _st[i];
solve(l, mid, x, x+lo-1), solve(mid+1, r, y-hi+n+1, y);
}
intmain(){
scanf("%d%d", &n, &m);
for (int i = 1, x; i <= m; ++i) {
scanf("%d", &x);
nx[i] = hd[x], hd[x] = i;
}
for (int i = 1; i <= n; ++i)
scanf("%d", &st[i].w), st[i].id = i;
scanf("%d", &k);
for (int i = 1; i <= k; ++i) {
scanf("%d%d%d", L+i, R+i, a+i);
if (R[i] < L[i]) R[i] += m;
}
solve(1, k+1, 1, n);
for (int i = 1; i <= n; ++i)
ans[i]==k+1 ? puts("NIE") : printf("%d\n", ans[i]);
return0;
}
cdq分治
#include<iostream>#include<algorithm>usingnamespacestd;
constint N = 1e5 + 7;
structNode {int a, b, c, ans, ct; } a[N], b[N];
int n, cnt[N<<1], biT[N<<1], k;
voidadd(int x, int v){
while (x <= k) biT[x] += v, x += x & -x;
}
intquery(int x){
int ans = 0;
while (x) ans += biT[x], x &= x-1;
return ans;
}
boolcmpb(Node &x, Node &y){
if (x.b == y.b) return x.c < y.c;
return x.b < y.b;
}
voidcdq(int l, int r){
if (l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid), cdq(mid+1, r);
sort(a+l, a+mid+1, cmpb), sort(a+mid+1, a+r+1, cmpb);
int j = l;
for (int i = mid+1; i <= r; ++i) {
while (a[j].b<=a[i].b && j<=mid)
add(a[j].c, a[j].ct), ++j;
a[i].ans += query(a[i].c);
}
for (int i = l; i < j; ++i) add(a[i].c, -a[i].ct);
}
intmain(){
int m;
scanf("%d%d", &m, &k);
for (int i = 1; i <= m; ++i)
scanf("%d%d%d", &b[i].a, &b[i].b, &b[i].c);
sort(b+1, b+m+1, [](Node &x, Node &y){
if (x.a == y.a) {
if (x.b == y.b) return x.c < y.c;
return x.b < y.b;
}
return x.a < y.a;
});
int ct = 0;
for (int i = 1; i <= m; ++i) {
++ct;
if (b[i].a!=b[i+1].a || b[i].b!=b[i+1].b || b[i].c!=b[i+1].c)
a[++n] = b[i], a[n].ct = ct, ct = 0;
}
cdq(1, n);
for (int i = 1; i <= n; ++i)
cnt[a[i].ans+a[i].ct-1] += a[i].ct;
for (int i = 0; i < m; ++i)
printf("%d\n", cnt[i]);
return0;
}
bitset 版本
bitset 最多声明 10 万大小,1 万组,这里循环利用。
#include<iostream>#include<bitset>#include<algorithm>usingnamespacestd;
constint N = 1e5 + 3;
int p[3][N], a[3][N], w[N];
bitset<N> b[9995], s;
intmain(){
int *tp, *ta, n;
scanf("%d%*d", &n);
for (int i = 1; i <= n; ++i)
for (int j = 0; j < 3; ++j)
scanf("%d", a[j]+i), p[j][i] = i;
for (int i = 0; i < 3; ++i)
sort(p[i]+1, p[i]+n+1, [=](int x, int y) { return a[i][x]<a[i][y]; });
for (int l = 1, r; l <= n; l = r+1) {
r = min(l+9991, n);
for (int i = l; i <= r; ++i) b[i-l].set();
for (int i = 0; i < 3; ++i) {
tp = p[i], ta = a[i], s.reset();
for (int j = 1, k = 1; j <= n; ++j) {
int x = tp[j];
while (k<=n && ta[tp[k]]<=ta[x]) s[tp[k++]] = 1;
if (l<=x && x<=r) b[x-l] &= s;
}
}
for (int i = l; i <= r; ++i) ++w[b[i-l].count()];
}
for (int i = 1; i <= n; ++i) printf("%d\n", w[i]);
return0;
}