BZOJ 2989 数列
2017-03-16 08:00
330 查看
CDQ分治+树状数组
注意到这题修改操作对询问的贡献独立,且修改之间互不影响,考虑CDQ分治。用左边的修改更新右边,只需按x排序所有事件点,树状数组维护y轴即可。
不知道KD树能不能搞一搞?
注意到这题修改操作对询问的贡献独立,且修改之间互不影响,考虑CDQ分治。用左边的修改更新右边,只需按x排序所有事件点,树状数组维护y轴即可。
不知道KD树能不能搞一搞?
#include<cstdio> #include<algorithm> #define lowbit(_i) (_i&-_i) #define N 800005 #define BASE 400005 using namespace std; namespace runzhe2000 { int read() { int r = 0; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()); for(; c >='0' && c <='9'; r = r*10+c-'0', c = getchar()); return r; } char str[10]; int n, Q, a , qcnt, ans ; struct BIT { int t ; void mod(int x, int v){for(;x<N;x+=lowbit(x)) t[x] += v;} int _que(int x){int r = 0; for(;x;x-=lowbit(x)) r += t[x]; return r;} int que(int l, int r){return _que(r) - _que(l-1);} } bit; struct que { int type, x, y, d, id; // 0 insert 1 query // 1 add_query -1 del_query bool operator < (const que &that) const { if(x != that.x) return x < that.x; else return type > that.type; } }q , qq[N<<1]; void dc(int l, int r) { if(l == r) return; int mid = (l+r)>>1, qqcnt = 0; for(int i = l; i <= mid ; i++) if(!q[i].type) qq[++qqcnt] = q[i]; for(int i = mid+1; i <= r; i++) if(q[i].type) { qq[++qqcnt] = (que){1 , q[i].x - q[i].d, q[i].y, q[i].d, q[i].id}; qq[++qqcnt] = (que){-1, q[i].x + q[i].d, q[i].y, q[i].d, q[i].id}; } sort(qq+1, qq+1+qqcnt); for(int i = 1; i <= qqcnt; i++) { if(qq[i].type == 0) bit.mod(qq[i].y, 1); else if(qq[i].type == 1) ans[qq[i].id] -= bit.que(qq[i].y - qq[i].d, qq[i].y + qq[i].d); else ans[qq[i].id] += bit.que(qq[i].y - qq[i].d, qq[i].y + qq[i].d); } for(int i = 1; i <= qqcnt; i++) if(qq[i].type == 0) bit.mod(qq[i].y, -1); dc(l,mid); dc(mid+1,r); } void main() { n = read(); Q = read(); for(int i = 1; i <= n; i++) { a[i] = read(); q[++qcnt] = (que){0, i+a[i]+BASE, i-a[i]+BASE, 0, 0}; } for(int i = 1; i <= Q; i++) { scanf("%s",str); if(str[0] == 'Q'){int p = read(); q[++qcnt] = (que){1, p+a[p]+BASE, p-a[p]+BASE, read(), i};} else {int p = read(); a[p] = read(); q[++qcnt] = (que){0, p+a[p]+BASE, p-a[p]+BASE, 0, 0};} } dc(1,qcnt); for(int i = 1; i <= Q; i++) if(ans[i]) printf("%d\n",ans[i]); } } int main() { runzhe2000::main(); }
相关文章推荐
- [bzoj2989]数列_KD-Tree_旋转坐标系
- [BZOJ]4170: 极光 2989: 数列 CDQ分治+树状数组
- BZOJ_2989_数列&&BZOJ_4170_极光_KDTree
- bzoj 2989: 数列&4170: 极光
- BZOJ2989 数列(二进制分组)
- BZOJ2989 数列/BZOJ4170 极光
- 【BZOJ2989】数列 kd-tree
- 【bzoj2989】数列 KD-tree+旋转坐标系
- 【bzoj2989】【数列】【cdq分治+树状数组】
- 【线段树】BZOJ2989 数列
- BZOJ 2989 数列 变换坐标系 主席树
- BZOJ1500:[NOI2005]维修数列——题解
- BZoj 1500 [NOI2005]维修数列 (Splay 模板)
- BZOJ 2326 HNOI 2011 数学作业 矩阵乘法求数列第n项
- BZOJ 1500: [NOI2005]维修数列
- BZOJ3142 [Hnoi2013]数列
- bzoj 1485: [HNOI2009]有趣的数列 (卡特兰数)
- BZOJ 1500 [NOI2005 D1T2] 维修数列
- 【BZOJ-1500】维修数列 Splay
- bzoj 4028 : [HEOI2015]公约数数列