BZOJ1176: [Balkan2007]Mokia kdtree

来源:互联网 发布:淘宝购物车流程图 编辑:程序博客网 时间:2024/05/15 01:01

题目大意:同2683
修改操作数M <= 160000,询问数Q <= 10000
多了个初始值,查询时直接加上就好。

#include<cstdio>#include<algorithm>#include<cmath>#define u size_tusing std::nth_element;bool cmp;struct pnt{    u pos[2];    pnt(u a,u b){pos[0]=a,pos[1]=b;}    inline u& operator [] (u x){return pos[x];}    inline bool operator < (const pnt &p) const    {return pos[0]<p.pos[0]&&pos[1]<p.pos[1];}    inline bool operator == (const pnt &p) const    {return pos[0]==p.pos[0]&&pos[1]==p.pos[1];}    inline bool operator <= (const pnt &p) const    {return pos[0]<=p.pos[0]&&pos[1]<=p.pos[1];}};inline void min(u &a,u b){if(b<a) a=b;}inline void max(u &a,u b){if(a<b) a=b;}inline void min(pnt &a,pnt &b){min(a[0],b[0]),min(a[1],b[1]);}inline void max(pnt &a,pnt &b){max(a[0],b[0]),max(a[1],b[1]);}struct node{    node *l,*r;    pnt p,mn,mx;    u v,sum,sz;    node(const pnt &p,u v):l(0),r(0),p(p),mn(p),mx(p),v(v),sum(v),sz(1){}    u getsum(pnt &__mn,pnt &__mx)    {        if(__mn<=mn&&mx<=__mx) return sum;        if(__mn[0]>mx[0]||__mn[1]>mx[1]||__mx[0]<mn[0]||__mx[1]<mn[1]) return 0;        u __sum=0;        if(__mn<=p&&p<=__mx) __sum+=v;        if(l) __sum+=l->getsum(__mn,__mx);        if(r) __sum+=r->getsum(__mn,__mx);        return __sum;    }    inline void reset()    {        l=r=0;        mn=mx=p;        sum=v;        sz=1;    }    inline void* operator new(u)    {        static node *s,*t;        static u size=sizeof(node)<<12;        if(s==t) s=(node*)malloc(size),t=s+(1<<12);        return s++;    }    inline void up()    {        mn=mx=p,sum=v,sz=1;        if(l)        {            min(mn,l->mn),max(mx,l->mx);            sum+=l->sum;            sz+=l->sz;        }        if(r)        {            min(mn,r->mn),max(mx,r->mx);            sum+=r->sum;            sz+=r->sz;        }    }}*ar[200001];inline bool less(node *a,node *b){return a->p[cmp]<b->p[cmp];}u top=0;const double A=0.7,B=log(1.0/0.7);struct kdtree{    node *rt;    kdtree():rt(0){}    bool insert(node*& x,node *y,u h=0,bool comp=0)    {        if(!x)        {            x=new node(*y);            return h>log(rt->sz)/B;        }        if(x->p==y->p) return x->v+=y->v,x->sum+=y->v,0;        cmp=comp;        if(less(y,x))        {            bool kre=insert(x->l,y,h+1,!comp);            x->up();            if(kre) return x->l->sz>x->sz*A?rebuild(x,comp),0:1;            return 0;        }        else        {            bool kre=insert(x->r,y,h+1,!comp);            x->up();            if(kre)return x->r->sz>x->sz*A?rebuild(x,comp),0:1;            return 0;        }    }    inline void insert(pnt p,u v)    {        node it(p,v);        insert(rt,&it);    }    void tour(node *x)    {        if(!x) return;        tour(x->l);        ar[++top]=x;        tour(x->r);        x->reset();    }    void rebuild(node*& x,bool comp,u l,u r)    {        if(r<l) {x=0;return;}        cmp=comp;        u mid=l+r>>1;        nth_element(ar+l,ar+mid,ar+r+1,less);        x=ar[mid];        rebuild(x->l,!comp,l,mid-1),rebuild(x->r,!comp,mid+1,r);        x->up();    }    inline void rebuild(node*& x,bool comp)    {        top=0;        tour(x);        rebuild(x,comp,1,top);    }    inline u query(u x1,u y1,u x2,u y2)    {        if(!rt) return 0;        pnt mn(x1,y1),mx(x2,y2);        return rt->getsum(mn,mx);    }}tr;u s,n,o,x,y,a,z,w;int main(){    scanf("%u%u",&s,&n);    while(scanf("%u",&o)==1)    {        if(o==3) break;        if(o==1)        {            scanf("%u%u%u",&x,&y,&a);            tr.insert(pnt(x,y),a);        }        else        {            scanf("%u%u%u%u",&x,&y,&z,&w);            printf("%u\n",tr.query(x,y,z,w)+(z-x+1)*(w-y+1)*s);        }    }    return 0;}
0 0
原创粉丝点击