BZOJ4066: 简单题

题目大意:两个操作,单点修改,矩形求和,强制在线,矩阵边长≤50W


强制在线不能用cdq,所以只能上K-DTREE了,然而这题动态加点,所以每插入一定次数就暴力重建一次,这样时间复杂度大概是O(Nsqrt(N))级别的,我也不太清楚


#pragma GCC optimize("O2")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200010
using namespace std;
struct node
{
	int v[2],mx[2],mn[2],ch[2],w,sum;
}a[N];
int D;
bool cmp(node x,node y)
{
	return x.v[D]<y.v[D];
}
void pup(int x)
{
	int i,j;
	for(i=0;i<2;i++)
	{
		a[x].mn[i]=a[x].mx[i]=a[x].v[i];
		a[x].sum=a[x].w;
	}
	for(i=0;i<2;i++)
	if(a[x].ch[i])
	{
		a[x].sum+=a[a[x].ch[i]].sum;
		for(j=0;j<2;j++)
		{
			a[x].mn[j]=min(a[x].mn[j],a[a[x].ch[i]].mn[j]);
			a[x].mx[j]=max(a[x].mx[j],a[a[x].ch[i]].mx[j]);
		}
	}
}
int build(int l,int r,int now)
{
	int mid=(l+r)>>1;
	D=now;
	nth_element(a+l,a+mid,a+r+1,cmp);
	if(l<mid) a[mid].ch[0]=build(l,mid-1,now^1);
	else a[mid].ch[0]=0;
	if(r>mid) a[mid].ch[1]=build(mid+1,r,now^1);
	else a[mid].ch[1]=0;
	int i;
	pup(mid);
	return mid;
}
int cnt=0,root;
void add(int &k,int x,int now)
{
	if(!k){k=x;pup(k);return;}
	if(a[x].v[now]<a[k].v[now])
	add(a[k].ch[0],x,now^1);
	else
	add(a[k].ch[1],x,now^1);
	pup(k);
}
int check(int k,int x4,int x5,int y4,int y5)
{
	if(!k) return 0;
	int MN[2]={x4,y4},MX[2]={x5,y5};
	if(a[k].mn[0]>=MN[0]&&a[k].mx[0]<=MX[0]&&a[k].mn[1]>=MN[1]&&a[k].mx[1]<=MX[1]) return a[k].sum;
	if(a[k].mn[0]>MX[0]||a[k].mx[0]<MN[0]||a[k].mn[1]>MX[1]||a[k].mx[1]<MN[1]) return 0;
	int ret=check(a[k].ch[0],x4,x5,y4,y5)+check(a[k].ch[1],x4,x5,y4,y5);
	if(a[k].v[0]<=MX[0]&&a[k].v[0]>=MN[0]&&a[k].v[1]<=MX[1]&&a[k].v[1]>=MN[1]) ret+=a[k].w;
	return ret;
}
char xB[1<<15],*xS=xB,*xT=xB;
#define getc() (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
inline int read(){
    char ch=getc();
    int f=1,x=0;
    while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getc();}
    return x*f;
}
int main()
{
	int n;
	n=read();
	int o,x4,x5,y4,y5;
	int LA=0;
	while(o=read())
	{
		if(o==1)
		{
			cnt++;
			a[cnt].v[0]=read();a[cnt].v[1]=read();a[cnt].w=read();
			a[cnt].v[0]^=LA;
			a[cnt].v[1]^=LA;
			a[cnt].w^=LA;
			if(cnt%10000==0) root=build(1,cnt,0);
			else
			{
				a[cnt].ch[0]=a[cnt].ch[1]=0;
				add(root,cnt,0);
			}
		}
		else if(o==2)
		{
			x4=read();y4=read();x5=read();y5=read();
			x4^=LA;x5^=LA;
			y4^=LA;y5^=LA;
			LA=check(root,x4,x5,y4,y5);
			printf("%d\n",LA);
		}
		else break;
	}
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值