lp4390 [BOI2007]Mokia 摩基亚

题目概述:
  带修改的二维数点。

题目思路:
  把一个询问拆成4个,那么我们很容易想到cdq分治,直接做即可。
  用一些小技巧可以优化代码。老久没写cdq了,果然挂了,i=j=1是怎么回事。

题目代码:

#include<cstdio>
#include<algorithm>

const int MaQ1=10000,MaQ2=160000;
#define opt1 (true)
#define opt2 (false)

struct ques{
    int t,x,y,num;
    bool opt;
    friend bool operator <(ques a,ques b){
        if(a.t!=b.t)
            return a.t<b.t;
        return a.x+a.y>b.x+b.y;
    }
}q[MaQ1+MaQ2*4+5],ls[MaQ1+MaQ2*4+5];

int n,m,k;
inline int lowbit(int a){return a&-a;}
int c[2000005];
void add(int val,int r){
    for(;val<=n;val+=lowbit(val)) c[val]+=r;
    return ;
}
int que(int val){
    int r;
    for(r=0;val;val-=lowbit(val)) r+=c[val];
    return r;
}
int st[1000005],con;
void clear(int val){
    for(;val<=n;val+=lowbit(val)) c[val]=0;
    return ;
}

void prout(){
    /*printf("\n");
    for(int i=1;i<=k;i++){
        printf("%d:%d %d %d\n",i,q[i].t,q[i].x,q[i].y);
    }
    printf("\n");*/
    return ;
}

void cdq(int l,int r){
    if(l==r) return ;

    #define mid (l+r>>1)
    cdq(l,mid);cdq(mid+1,r);

    //BUG A
    //int i=1,j=1,k=mid+1;
    int i=l,j=l,k=mid+1;
    while(j<=mid&&k<=r){
        if(q[j].x<=q[k].x){
            if(q[j].opt){
                add(q[j].y,q[j].num);
                st[con++]=q[j].y;
            }
            ls[i++]=q[j++];
        }
        else{
            if(!q[k].opt)
                q[k].num+=que(q[k].y);
            ls[i++]=q[k++];
        }
    }
    while(j<=mid){
        if(q[j].opt){
            add(q[j].y,q[j].num);
            st[con++]=q[j].y;
        }
        ls[i++]=q[j++];
    }
    while(k<=r){
        if(!q[k].opt)
            q[k].num+=que(q[k].y);
        ls[i++]=q[k++];
    }
    #undef mid

    for(int i=0;i<con;i++) clear(st[i]);
    con=0;
    for(int i=l;i<=r;i++) q[i]=ls[i];

    prout();
    return ;
}

int main(){
    scanf("%*d%d",&n);
    int opt;
    while(true){
        scanf("%d",&opt);
        if(opt==3) break;
        ++m;
        if(opt==1){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            q[++k]= (ques) {m,x,y,z,1};
        }
        else{
            int x1,y1,x2,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            q[++k]=(ques) {
                m,x1-1,y1-1,0,opt2
            };
            q[++k]=(ques) {
                m,x1-1,y2,0,opt2
            };
            q[++k]=(ques) {
                m,x2,y1-1,0,opt2
            };
            q[++k]=(ques) {
                m,x2,y2,0,opt2
            };
        }
    }
    prout();
    cdq(1,k);
    std::sort(q+1,q+k+1);
    prout();
    int now=1;
    for(int i=1;i<=m;i++){
        if(q[now].opt==opt1){++now;continue;}
        if(q[now].opt==opt2)
            printf("%d\n",q[now].num+q[now+3].num-q[now+1].num-q[now+2].num),now+=4;
    }
    return 0;
}

 

posted @ 2018-12-27 22:30  臼邦庶民  阅读(130)  评论(0编辑  收藏  举报