[BZOJ 2683] 简单题 (CDQ分治)

[BZOJ 2683] 简单题 (CDQ分治)

题面

N*N矩阵,支持单点修改,查询某一个子矩阵内的和

\(n \leq 500000\),操作数\(\leq 200000\)

分析

首先运用二维前缀和的思想,把子矩阵的和拆成四个前缀和。

然后把询问和修改看成(x,y,t)的三元组,t表示当前是第几次操作。然后就变成三维偏序问题,对于每个询问,找x,y,t均比它小的修改操作,再求和。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 2000000
#define maxm 2000000
using namespace std;
int n,m,cnt,qcnt;
typedef int ll;
struct node{
    int a;//x
    int b;//y
    int c;//时间戳 
    int type;//询问(2)还是修改(1) 
    int val; //如果是修改,就是修改值。如果是询问,就是当前符号 
    int id;//对应几号询问 
    ll ans; 
    node(){
        
    }
    node(int _a,int _b,int _c,int _type,int _val){
        a=_a;
        b=_b;
        c=_c;
        type=_type;
        val=_val;
        id=ans=0;
    }
    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{
    ll c[maxn+5];
    inline int lowbit(int x){
        return x&(-x);
    }
    inline void update(int pos,int val){
        for(int i=pos;i<=maxn;i+=lowbit(i)) c[i]+=val;
    }
    inline ll 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){
    int mid=(l+r)>>1;
    if(l==r) return;
    cdq_divide(l,mid);
    cdq_divide(mid+1,r);
//  sort(q+l,q+mid+1,cmpb);
//  sort(q+mid+1,q+1+r,cmpb);
    //这里不要大力sort,会TLE,回溯的时候合并就可以了
    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,q[ptr].val);
        }
        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,-q[i].val);
    int pl=l,pr=mid+1;
    int num=l-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];
}

ll ans[maxn+5];
int main(){
    int cmd,x1,y1,x2,y2,v;
    scanf("%d",&n);
    while(1){
        scanf("%d",&cmd);
        if(cmd==1){
            scanf("%d %d %d",&x1,&y1,&v);
            m++;
            q[++cnt]=node(x1,y1,m,1,v);
        }else if(cmd==2){
            scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
            m++;
            qcnt++;
            q[++cnt]=node(x2,y2,m,2,1,qcnt);
            q[++cnt]=node(x1-1,y2,m,2,-1,qcnt);
            q[++cnt]=node(x2,y1-1,m,2,-1,qcnt);
            q[++cnt]=node(x1-1,y1-1,m,2,1,qcnt);
        }else{
            break;
        } 
    } 
    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]);
} 

猜你喜欢

转载自www.cnblogs.com/birchtree/p/11366381.html