Bzoj_4066 简单题

传送门

https://www.lydsy.com/JudgeOnline/problem.php?id=4066

题解

由于是在线的,我们建棵KDtree。因为存在插入操作,我们可以用一种暴力方法维护平衡性:每插入一定次数,就重建整棵树。这样查询复杂度就不会过高。

``` cpp

pragma GCC optimize(3)

include

include

include

include

include

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=x10+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;
}

```

转载于:https://www.cnblogs.com/Alseo_Roplyer/p/10284351.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值