题目大意:n*n矩阵,单点加,矩形查和
1<=N<=500000,操作数不超过200000个,内存限制20M。
正解是cdq分治,强行拿kdtree卡了过去。
1.n是矩形大小,不是操作数量,不要被坑了
2.kdtree是空树直接返回0,否则就崩了
3.nth_element的写法是(begin,nth,end,comp),话说我之前那个崂山白花蛇草水错成那样都能过。。。
4.kdtree的重构遍历千万不能遍历前先清空左右儿子。。。
时限50秒,43秒成功进入最后一页,然而号称卡内存的这道题我只用了6124K
#include<cstdio>
#include<algorithm>
#include<cmath>
#define u size_t
using 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 n,o,x,y,a,z,w;
int main()
{
scanf("%u",&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));
}
}
return 0;
}