Bzoj_4066 简单题
传送门
https://www.lydsy.com/JudgeOnline/problem.php?id=4066
题解
由于是在线的,我们建棵KDtree。因为存在插入操作,我们可以用一种暴力方法维护平衡性:每插入一定次数,就重建整棵树。这样查询复杂度就不会过高。
#pragma GCC optimize(3)
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2e5;
const int limit=8000;
int n,m,siz,last_ans,D;
int read()
{
int x=0,f=1;char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*f;
}
struct node
{
node *s[2];
int mx[2],mn[2],d[2];
int val,sum;
}space[maxn+8],*q;
bool cmp(node x,node y){return x.d[D]<y.d[D];}
node *newnode(int x,int y,int v)
{
node *z=&space[++siz];
z->d[0]=z->mx[0]=z->mn[0]=x;
z->d[1]=z->mx[1]=z->mn[1]=y;
z->val=z->sum=v;
return z;
}
void ckmax(int &a,int b){if (a<b) a=b;}
void ckmin(int &a,int b){if (a>b) a=b;}
struct K_D_Tree
{
node *root;
void update(node *p)
{
p->sum=p->val;
if (p->s[0]!=NULL)
{
p->sum+=p->s[0]->sum;
ckmax(p->mx[0],p->s[0]->mx[0]);
ckmax(p->mx[1],p->s[0]->mx[1]);
ckmin(p->mn[0],p->s[0]->mn[0]);
ckmin(p->mn[1],p->s[0]->mn[1]);
}
if (p->s[1]!=NULL)
{
p->sum+=p->s[1]->sum;
ckmax(p->mx[0],p->s[1]->mx[0]);
ckmax(p->mx[1],p->s[1]->mx[1]);
ckmin(p->mn[0],p->s[1]->mn[0]);
ckmin(p->mn[1],p->s[1]->mn[1]);
}
}
void clear(node *p)
{
p->s[0]=p->s[1]=NULL;
p->mx[1]=p->mn[1]=p->d[1];
p->mx[0]=p->mn[0]=p->d[0];
p->sum=p->val;
}
void modify(node *p)
{
p->sum+=q->val;
ckmax(p->mx[0],q->d[0]);
ckmax(p->mx[1],q->d[1]);
ckmin(p->mn[0],q->d[0]);
ckmin(p->mn[1],q->d[1]);
}
node *insert(node *p,int tmp_d)
{
if (p==NULL) return newnode(q->d[0],q->d[1],q->val);
modify(p);
if (p->d[0]==q->d[0]&&p->d[1]==q->d[1]) {p->val+=q->val;return p;}
if (q->d[tmp_d]<=p->d[tmp_d]) p->s[0]=insert(p->s[0],tmp_d^1);
else p->s[1]=insert(p->s[1],tmp_d^1);
return p;
}
node *build(int l,int r,int tmp_d)
{
D=tmp_d;int mid=(l+r)>>1;
nth_element(q+l,q+mid,q+r+1,cmp);
node *p=&q[mid];
clear(p);
if (l!=mid) p->s[0]=build(l,mid-1,tmp_d^1);
if (r!=mid) p->s[1]=build(mid+1,r,tmp_d^1);
update(p);
return p;
}
bool in_map(node *p,int l,int r,int L,int R)
{
return l<=p->mn[0]&&p->mx[0]<=r&&L<=p->mn[1]&&p->mx[1]<=R;
}
bool out_map(node *p,int l,int r,int L,int R)
{
return p->mn[0]>r||p->mx[0]<l||p->mn[1]>R||p->mx[1]<L;
}
int query(node *p,int l,int r,int L,int R)
{
if (p==NULL) return 0;
if (in_map(p,l,r,L,R)) return p->sum;
if (out_map(p,l,r,L,R)) return 0;
int tmp=0;
if (l<=p->d[0]&&p->d[0]<=r&&L<=p->d[1]&&p->d[1]<=R) tmp=p->val;
if (p->s[0]!=NULL) tmp+=query(p->s[0],l,r,L,R);
if (p->s[1]!=NULL) tmp+=query(p->s[1],l,r,L,R);
return tmp;
}
}KDT;
int main()
{
n=read();
m=limit;
q=&space[0];
while(1)
{
int opt=read();
if (opt==1)
{
q->d[0]=read()^last_ans,q->d[1]=read()^last_ans,q->val=read()^last_ans;
KDT.root=KDT.insert(KDT.root,0);
if (siz==m)
{
KDT.root=KDT.build(1,siz,0);
m+=limit;
}
}
if (opt==2)
{
int l=read()^last_ans,L=read()^last_ans,r=read()^last_ans,R=read()^last_ans;
printf("%d\n",last_ans=KDT.query(KDT.root,l,r,L,R));
}
if (opt==3) break;
}
return 0;
}
```