CDQ分治&整体二分练习1——P4390 [BOI2007]Mokia 摩基亚

蒟蒻的垂死挣扎

很裸的一道CDQ分治题,这题对于每个询问处理为二维前缀的形式,那么就可以分裂成四个查询,然后以时间、x、y三维做CDQ分治,大概怎么搞都可以吧。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define MOD 1000000007
#define N 210000
#define M 10010000
#define RG register

using namespace std;

inline ll read(){
    RG ll x=0,o=1; RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') o=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=((x<<3)+(x<<1))+ch-'0',ch=getchar();
    return x*o;
}

struct mona { int t,op,x,y; ll val,id,opt; } s[N],q[N];
inline bool cmp(mona x,mona y) { return x.t>1;
    CDQ(l,mid),CDQ(mid+1,r); RG int i,j,now;
    for(i=l,j=mid+1,now=l-1;i<=mid,j<=r;)
        if(s[i].xs[j].x&&j<=r) q[++now]=s[j++];
        else if(s[i].op==1&&i<=mid) q[++now]=s[i++];
        else q[++now]=s[j++];
    while(i<=mid) q[++now]=s[i++];
    while(j<=r)   q[++now]=s[j++];
    for(i=l;i<=r;++i){
        s[i]=q[i];
        if(s[i].op==1&&s[i].t<=mid) Update(s[i].y,s[i].val);
        if(s[i].op==2&&s[i].t>mid)  s[i].val+=Query(s[i].y);
    }
    for(i=l;i<=r;++i) if(s[i].op==1&&s[i].t<=mid) Update(s[i].y,-s[i].val);
}

int main(){
    read(),n=read(); RG int op,t=0;
    while((op=read())!=3)
        if(op==1) s[++t]=(mona) { t,op,read(),read(),read() };
        else{
            int x=read(),y=read(),tx=read(),ty=read(); ++top;
            s[++t]=(mona) { t,op,x-1,y-1,0,top,+1 },s[++t]=(mona) { t,op,tx,ty,0,top,+1 };
            s[++t]=(mona) { t,op,x-1,ty,0,top,-1 },s[++t]=(mona) { t,op,tx,y-1,0,top,-1 };
        }
    CDQ(1,t);
    for(RG int i=1;i<=t;++i) if(s[i].op==2) ans[s[i].id]+=s[i].opt*s[i].val;
    for(RG int i=1;i<=top;++i) printf("%lld\n",ans[i]);
}

 

你可能感兴趣的:(分治-CDQ分治&&整体二分)