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;
}
	
	```
posted @ 2019-01-17 20:17  Alseo_Roplyer  阅读(181)  评论(0编辑  收藏  举报