[BZOJ 2989] Sequence (CDQ partition + Manhattan distance and cut Chebyshev distance conversion)

[BZOJ 2989] Sequence (CDQ partition)

Face questions

Given a positive integer n, the number of columns of length a [i].

graze define two positions of both the position difference is the difference between the value and that graze (x, y) = | xy | + | a [x] -a [y] |.

2 operating (k is a positive integer):

1.Modify xk: the value of x number of modifications to be k.

2.Query xk: There are several interrogation i satisfies graze (x, i) <= k. Because persistable popular data structures, asked only to consider the current number of columns, but also consider any historical version, that is, any value appeared statistics anywhere on the current of a [x] of graze value <= log k. (A position amended several times for the same value, according to statistics many times)

analysis

It is said that positive solutions are binary packet + Chairman tree?

Observed \ (| the XY | + | A [the X-] -a [the y-] | \) , we think of Manhattan distance. So we put (x, a [x]) regarded as a point on a two-dimensional plane, and the plane to the query is a certain distance from the point <= k is the number of points. While also avoiding this problem may be persistent, since the a [x] is modified to k, corresponding to a new point.

A certain point on a plane from the set of points k = Manhattan (Manhattan distance next round) is an angled 45 °, side length \ (\ frac {\ sqrt { 2}} {2} k \) square. We find the answer in the square is the number of points

[Picture Reprinted from https://www.cnblogs.com/SGCollin/p/9636955.html]

Such a request is not very good point distance. But we know that the next round cut than the distance Schiff is a four-sided square are parallel to the axis. Therefore, we can turn into tangential Manhattan distance corresponding Chebyshev distance. NOTE: \ ((x_1, Y_1) cut and (x_2, y_2) Chebyshev distance max (| x_1-x_2 |, | y_1-y_2 |) \)

考虑把两个点转化成\((x_1+y_1,x_1-y_1),(x_2+y_2,x_2-y_2)\),容易发现新点的切比雪夫距离和原来点的曼哈顿距离相同.

那么我们只要把询问和修改的每个点都转成(x+y,x-y)的形式,然后问题就变成在把原来查询的正方形转换后新的正方形里点的个数。由于边都平行于坐标轴,这是一个经典的三维偏序问题,详情可参考[BZOJ 2683] 简单题 (CDQ分治)

代码

//首先把询问转成曼哈顿距离,(i,a[i])看成一个点 
//注意到曼哈顿距离下的圆为斜45度正方形,圆内点的个数即为答案
//斜的正方形不好查询,考虑切比雪夫距离下的圆为平行于坐标轴的正方形 (相当于逆时针旋转45度) 
//把正方形角上的点以及更新的点曼哈顿距离下的坐标转成切比雪夫距离下的坐标
//再在新正方形里二维前缀和即可 
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 1000000
using namespace std;
int n,m,tim,cnt,qcnt;
int xx[maxn+5],yy[maxn+5];
inline void change(int& x,int& y){//改变坐标系 
    int xx=x,yy=y;
    x=xx+yy;
    y=xx-yy;
}
struct node{
    int a;
    int b;
    int c;
    int type;
    int val;
    int id;
    int ans;
    node(){
        
    }   
    node(int _a,int _b,int _c,int _type){
        a=_a;
        b=_b;
        c=_c;
        type=_type;
    }
    node(int _a,int _b,int _c,int _type,int _val,int _id){
        a=_a;
        b=_b;
        c=_c;
        type=_type;
        val=_val;
        id=_id;
        ans=0;
    }
}q[maxn+5]; 
int cmpa(node p,node q){
    if(p.a==q.a){
        if(p.b==q.b) return p.c<q.c;
        else return p.b<q.b;
    }else return p.a<q.a;
}
int cmpb(node p,node q){
    if(p.b==q.b) return p.c<q.c;
    else return p.b<q.b;
}


struct fenwick_tree{
    int c[maxn+5];
    inline int lowbit(int x){
        return x&(-x);
    }
    inline void update(int pos,int val){
        for(int i=pos;i<=tim;i+=lowbit(i)) c[i]+=val;
    }
    inline int query(int pos){
        int ans=0;
        for(int i=pos;i>0;i-=lowbit(i)) ans+=c[i];
        return ans; 
    }
}T;
node tmp[maxn+5];
void cdq_divide(int l,int r){//orz cdq 
    if(l==r) return;
    int mid=(l+r)>>1;
    cdq_divide(l,mid);
    cdq_divide(mid+1,r);
    int ptr=l-1;
    for(int i=mid+1;i<=r;i++){
        while(ptr<mid&&q[ptr+1].b<=q[i].b){
            ptr++;
            if(q[ptr].type==1) T.update(q[ptr].c,1);
        }
        if(q[i].type==2) q[i].ans+=T.query(q[i].c);
    } 
    for(int i=l;i<=ptr;i++) if(q[i].type==1) T.update(q[i].c,-1);
    
    int num=l-1;
    int pl=l,pr=mid+1;
    while(pl<=mid&&pr<=r){
        if(cmpb(q[pl],q[pr])) tmp[++num]=q[pl++];
        else tmp[++num]=q[pr++];
    }
    while(pl<=mid) tmp[++num]=q[pl++];
    while(pr<=r) tmp[++num]=q[pr++]; 
    for(int i=l;i<=r;i++) q[i]=tmp[i];
} 

char cmd[10]; 
int ans[maxn+5];
int main(){
    int p,k;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        xx[i]=i;
        scanf("%d",&yy[i]);
        tim++;
        q[++cnt]=node(xx[i]+yy[i],xx[i]-yy[i],tim,1);
    }
    for(int i=1;i<=m;i++){
        scanf("%s",cmd);
        if(cmd[0]=='M'){
            scanf("%d %d",&p,&k);
            tim++;
            yy[p]=k;
            q[++cnt]=node(xx[p]+yy[p],xx[p]-yy[p],tim,1); 
        }else{
            int x1,y1,x2,y2;
            scanf("%d %d",&p,&k);
            x1=xx[p]-k;
            y1=yy[p];
            x2=xx[p]+k;
            y2=yy[p];
            change(x1,y1);
            change(x2,y2);
            tim++;
            qcnt++;
            q[++cnt]=node(x2,y2,tim,2,1,qcnt);
            q[++cnt]=node(x1-1,y2,tim,2,-1,qcnt);
            q[++cnt]=node(x2,y1-1,tim,2,-1,qcnt);
            q[++cnt]=node(x1-1,y1-1,tim,2,1,qcnt); 
        }
    }
    sort(q+1,q+1+cnt,cmpa);
    cdq_divide(1,cnt);
    for(int i=1;i<=cnt;i++){
        if(q[i].type==2) ans[q[i].id]+=q[i].val*q[i].ans;
    }
    for(int i=1;i<=qcnt;i++) printf("%d\n",ans[i]);
} 

Guess you like

Origin www.cnblogs.com/birchtree/p/11366460.html