https://www.lydsy.com/JudgeOnline/problem.php?id=4066
很快就想到了,维护子树超平面,如果要求的范围完整包含这个子树,就直接加sum,否则看是否有相交,再考虑进入子树。
因为一直insert,kd树可能无法保证复杂度,所以要10000个点重构一次,复杂度是20*2e5复杂度
然后写完了,查了一晚上错,再重写了一遍,没找出来错误
然后开始二分抄代码,最后几乎全抄了才过了
心态崩了
弃疗.jpg
#include<bits/stdc++.h>
using namespace std;
const int maxl=2e5+10;
int n,idx,cnt,ans,root;
struct point
{
int x[2],val;
point(int a=0,int b=0,int c=0){ x[0]=a; x[1]=b; val=c; }
inline int operator [] (int i){ return x[i]; }
bool operator < (const point &b)const
{
return x[idx]<b.x[idx];
}
}a[maxl];
struct kdtree
{
int l,r,sum;
int mi[2],mx[2];
point t;
}tr[maxl];
inline void Update_mx(int &x,int y){ if(y>x) x=y; }
inline void Update_mi(int &x,int y){ if(y<x) x=y; }
void Update(int k){
for(int i=0;i<2;i++){
if(tr[k].l) Update_mx(tr[k].mx[i],tr[tr[k].l].mx[i]),Update_mi(tr[k].mi[i],tr[tr[k].l].mi[i]);
if(tr[k].r) Update_mx(tr[k].mx[i],tr[tr[k].r].mx[i]),Update_mi(tr[k].mi[i],tr[tr[k].r].mi[i]);
}
tr[k].sum=tr[tr[k].l].sum+tr[tr[k].r].sum+tr[k].t.val;
}
void Rebuild(int &k,int l,int r,int d){
idx=d; k=++cnt;
int mid=(l+r)>>1;
nth_element(a+l,a+mid,a+r+1);
tr[k].t=a[mid];
for(int i=0;i<2;i++) tr[k].mx[i]=tr[k].mi[i]=a[mid][i];
if(l<mid) Rebuild(tr[k].l,l,mid-1,d^1);
else tr[k].l=0;
if(r>mid) Rebuild(tr[k].r,mid+1,r,d^1);
else tr[k].r=0;
Update(k);
}
void Insert(int &k,point pt,int d){
if(!k){
k=++cnt; tr[k].t=pt; tr[k].sum=pt.val;
for(int i=0;i<2;i++) tr[k].mx[i]=tr[k].mi[i]=pt[i];
return;
}
if(pt[0]==tr[k].t[0] && pt[1]==tr[k].t[1]){ tr[k].sum+=pt.val; tr[k].t.val+=pt.val; return; }
idx=d;
if(pt<tr[k].t) Insert(tr[k].l,pt,d^1);
else Insert(tr[k].r,pt,d^1);
Update(k);
}
inline void prework()
{
scanf("%d",&n);
}
inline bool cross(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4){
if(x2<x3 || x1>x4 || y2<y3 || y1>y4) return false;
return true;
}
inline bool cover(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4){ //1-2 cover 3-4
if(y1<=y3 && y2>=y4 && x2>=x4 && x1<=x3) return true;
return false;
}
int Query(int k,int x1,int y1,int x2,int y2){
if(cover(x1,y1,x2,y2,tr[k].mi[0],tr[k].mi[1],tr[k].mx[0],tr[k].mx[1])) return tr[k].sum;
int tmp=0,l=tr[k].l,r=tr[k].r;
if(x1<=tr[k].t.x[0] && tr[k].t.x[0]<=x2 && tr[k].t.x[1]>=y1 && tr[k].t.x[1]<=y2)
tmp+=tr[k].t.val;
if(l && cross(x1,y1,x2,y2,tr[l].mi[0],tr[l].mi[1],tr[l].mx[0],tr[l].mx[1])) tmp+=Query(l,x1,y1,x2,y2);
if(r && cross(x1,y1,x2,y2,tr[r].mi[0],tr[r].mi[1],tr[r].mx[0],tr[r].mx[1])) tmp+=Query(r,x1,y1,x2,y2);
return tmp;
}
inline void mainwork()
{
int flag=10000,op;
while(~scanf("%d",&op)){
if(op==3) return;
if(op==1){
int x,y,c;
//x=in()^ans; y=in()^ans; c=in()^ans;
scanf("%d%d%d",&x,&y,&c);
x^=ans;y^=ans;c^=ans;
Insert(root,point(x,y,c),0);
if(cnt==flag){
for(int i=1;i<=cnt;i++) a[i]=tr[i].t,tr[i].sum=0;
int tmp=cnt; cnt=0; flag+=10000;
Rebuild(root,1,tmp,0);
}
}
else{
int x1,y1,x2,y2;
//x1=in()^ans; y1=in()^ans; x2=in()^ans; y2=in()^ans;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1^=ans;y1^=ans;x2^=ans;y2^=ans;
printf("%d\n",ans=Query(root,x1,y1,x2,y2));
}
}
}
int main()
{
prework();
mainwork();
return 0;
}