传送门:bzoj2683
题解
也可以用
cdq
c
d
q
分治做,这里用的
KD−tree
K
D
−
t
r
e
e
。
每个点上记录一下所管辖子树
x,y
x
,
y
的最大,最小值,以及总值,还有自己的点信息。
仿照替罪羊树,如果树太不平衡了直接暴力重构。
每次查询如果完整覆盖这个点子树,直接返回总值,如果完全无关,也直接返回0,否则先判断当前点再继续递归下去。
代码
#include<bits/stdc++.h>
#define gc getchar()
#define si isdigit(c)
#define lc t[k].ch[0]
#define rc t[k].ch[1]
#define mid (((l)+(r))>>1)
#define db double
using namespace std;
const int N=2e5+100,inf=0x7fffffff;
const db alp=0.77;
int n,op,rt,ans,cnt,sz[N],D;
struct P{
int x[2],v;
P(){}
P(int X,int Y,int V){x[0]=X,x[1]=Y,v=V;}
}p[N],mi,mx;
bool operator <(const P&a,const P&b){return a.x[D]<b.x[D];}
struct Node{
int x[2],y[2],val,ch[2];P pos;
Node(){}
Node(int Xa,int Xb,int Ya,int Yb,int Val,int LS,int RS,P ky)
{x[0]=Xa,x[1]=Ya,y[0]=Xb,y[1]=Yb,val=Val,ch[0]=LS,ch[1]=RS,pos=ky;}
}t[N];
struct Pool{
int que[N],top;
Pool(){top=0;}
inline int newnode(){
int re;
if(top) re=que[top--];
else re=++cnt;
sz[re]=1;return re;
}
inline void ins(int x){que[++top]=x;}
}Q;
char c;
inline int rd()
{
c=gc;int x=0,f=1;
for(;!si;c=gc) if(c=='-') f=-1;
for(;si;c=gc) x=x*10+(c^48);
return x*f;
}
inline void pushup(int k)
{
t[k].val=t[k].pos.v+t[lc].val+t[rc].val;
sz[k]=sz[lc]+sz[rc]+1;
t[k].x[0]=min(t[k].pos.x[0],min(t[lc].x[0],t[rc].x[0]));
t[k].x[1]=min(t[k].pos.x[1],min(t[lc].x[1],t[rc].x[1]));
t[k].y[0]=max(t[k].pos.x[0],max(t[lc].y[0],t[rc].y[0]));
t[k].y[1]=max(t[k].pos.x[1],max(t[lc].y[1],t[rc].y[1]));
}
inline void pai(int k,int num)
{
if(lc) pai(lc,num);
p[sz[lc]+num+1]=t[k].pos;Q.ins(k);
if(rc) pai(rc,sz[lc]+num+1);
}
inline void build(int &k,int l,int r,int d)
{
if(l>r) return;
k=Q.newnode();
D=d;nth_element(p+l,p+mid,p+r+1);
t[k].pos=p[mid];lc=rc=0;
build(lc,l,mid-1,d^1);build(rc,mid+1,r,d^1);
pushup(k);
}
inline void check(int &k,int d)
{
if(sz[k]*alp<sz[lc] || sz[k]*alp<sz[rc]){
pai(k,0);build(k,1,sz[k],d);
}
}
inline void ad(int &k,P pt,int d)
{
if(!k) {
k=Q.newnode();
t[k]=Node(pt.x[0],pt.x[0],pt.x[1],pt.x[1],pt.v,0,0,pt);
return;
}
if(pt.x[d]<=t[k].pos.x[d]) ad(lc,pt,d^1);
else ad(rc,pt,d^1);
pushup(k);check(k,d);
}
inline bool in(Node k)
{return (k.x[0]>=mi.x[0] && k.x[1]>=mi.x[1] && k.y[0]<=mx.x[0] && k.y[1]<=mx.x[1]);}
inline bool out(Node k)
{
if(k.y[0]<mi.x[0] || k.x[0]>mx.x[0]) return true;
if(k.y[1]<mi.x[1] || k.x[1]>mx.x[1]) return true;
return false;
}
inline bool inn(P a)
{return (a.x[0]>=mi.x[0] && a.x[0]<=mx.x[0] && a.x[1]>=mi.x[1] && a.x[1]<=mx.x[1]);}
inline int query(int k)
{
if(!k) return 0;
if(in(t[k])) return t[k].val;
if(out(t[k])) return 0;
int re=0;
if(inn(t[k].pos)) re=t[k].pos.v;
re+=query(lc)+query(rc);
return re;
}
int main(){
n=rd();
t[0]=Node(inf,-inf,inf,-inf,0,0,0,P(0,0,0));
for(;;){
op=rd();
if(op==3) break;
if(op==1){
mi.x[0]=rd();mi.x[1]=rd();mi.v=rd();
ad(rt,mi,0);
}else{
mi.x[0]=rd();mi.x[1]=rd();mx.x[0]=rd();mx.x[1]=rd();
printf("%d\n",ans=query(rt));
}
}
}