bzoj2989
坐标轴转化+cdq分治
我们发现那个绝对值不太好搞,于是我们把曼哈顿距离转为切比雪夫距离,x'=x-y,y'=x+y,这样两点之间距离就是max(|x1'-x2'|,|y1'-y2'|),这个距离要小于等于k,那么就是求转化后坐标系中在以x',y'为中心,边长为2k的正方形中的点数,每次修改就相当于加入一个点,计算平面点数就是cdq分治,按时间排序,对x分治,y插入树状数组,然后就做好了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int N = 400010, base = 200010; struct query { int x, y, opt, minus, id; query(int x = 0, int y = 0, int opt = 0, int minus = 0, int id = 0) : x(x), y(y), opt(opt), minus(minus), id(id) {} bool friend operator < (query A, query B) { return A.x == B.x ? A.id < B.id : A.x < B.x; } } q[N << 1]; vector<query> c; int n, Q, cnt, tot, m; int ans[N], a[N], tree[N << 1]; void update(int x, int d) { for(; x <= m; x += x & (-x)) tree[x] += d; } int ask(int x) { int ret = 0; for(; x; x -= x & (-x)) ret += tree[x]; return ret; } void cdq(int l, int r) { if(l >= r) return; int mid = (l + r) >> 1; cdq(l, mid); cdq(mid + 1, r); c.clear(); for(int i = l; i <= mid; ++i) if(q[i].opt == 1) c.push_back(q[i]); for(int i = mid + 1; i <= r; ++i) if(q[i].opt == 2) c.push_back(q[i]); sort(c.begin(), c.end()); for(int i = 0; i < c.size(); ++i) { query o = c[i]; if(o.opt == 1) update(o.y, 1); else ans[o.id] += ask(o.y) * o.minus; } for(int i = 0; i < c.size(); ++i) if(c[i].opt == 1) update(c[i].y, -1); } int main() { scanf("%d%d", &n, &Q); for(int i = 1; i <= n; ++i) { scanf("%d", &a[i]); q[++cnt] = query(i - a[i], i + a[i] + base, 1, 0, 0); m = max(m, i + a[i] + base); } for(int i = 1; i <= Q; ++i) { char s[10]; int x, y, k; scanf("%s", s); if(s[0] == 'M') { scanf("%d%d", &x, &y); q[++cnt] = query(x - y, x + y + base, 1, 0, 0), a[x] = y; m = max(m, x + y + base); } if(s[0] == 'Q') { scanf("%d%d", &x, &k); ++tot; m = max(m, x + a[x] + k + base); q[++cnt] = query(x - a[x] + k, x + a[x] + k + base, 2, 1, tot); q[++cnt] = query(x - a[x] - k - 1, x + a[x] - k - 1 + base, 2, 1, tot); q[++cnt] = query(x - a[x] - k - 1, x + a[x] + k + base, 2, -1, tot); q[++cnt] = query(x - a[x] + k, x + a[x] - k - 1 + base, 2, -1, tot); } } cdq(1, cnt); for(int i = 1; i <= tot; ++i) printf("%d\n", ans[i]); return 0; }