简单题(在线版)

题目大意:

给你一个N*N的棋盘,每个格子初始值v=0,支持两种操作:

1、v(x,y)+=k

2、query(x1,y1,x2,y2)

Input

输入文件第一行一个正整数N。
接下来每行一个操作。每条命令除第一个数字之外,均要异或上一次输出的答案last_ans。初始last_ans=0

Output

对于每个2操作,输出一个对应的答案。

Sample Input

4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3

Sample Output

3

5

Hint

1<=N<=500000,操作数不超过200000个,内存限制20M。
对于100%的数据,操作1中的A不超过2000。

昨天做了离线版本的,可以用cdq水过去,今天强制在线,是kd-tree的模板题,区间查询和。

#include<bits/stdc++.h>
using namespace std;
const int Maxn=500005;
typedef long long ll;
inline ll getll(){
	ll res=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c))res=res*10+c-'0',c=getchar();
	return res;
}
ll n,cnt,root,nowst;
ll ans;
struct Node{
	ll p[2],son[2];
	ll l[2],r[2];
	ll v,sum;
	inline void newnode(ll *_p,ll val){
		for(ll i=0;i<2;++i){
			p[i]=l[i]=r[i]=_p[i];
			son[i]=0;
		}
		v=sum=val;
	}
}a[Maxn],nd;
#define ls a[x].son[0]
#define rs a[x].son[1]
bool check(const Node&A,const Node&B){
	for(ll i=0;i<2;++i)
		if(A.p[i]!=B.p[i])return 0;
	return 1;
}
void maintain(ll x){
	a[x].sum=a[x].v;
	if(ls){
		for(ll i=0;i<2;++i)
			a[x].l[i]=min(a[x].l[i],a[ls].l[i]),
			a[x].r[i]=max(a[x].r[i],a[ls].r[i]);
		a[x].sum+=a[ls].sum;	
	}
	if(rs){
		for(ll i=0;i<2;++i)
			a[x].l[i]=min(a[x].l[i],a[rs].l[i]),
			a[x].r[i]=max(a[x].r[i],a[rs].r[i]);
		a[x].sum+=a[rs].sum;	
	}
}
void insert(ll &x,ll state){
	if(!x)return a[x=++cnt].newnode(nd.p,nd.v),void();
	if(check(a[x],nd))return a[x].v+=nd.v,a[x].sum+=nd.v,void();
	if(nd.p[state]<a[x].p[state])insert(ls,state^1);
	else insert(rs,state^1);
	maintain(x);
}
ll query(ll x,ll x1,ll y1,ll x2,ll y2){
	if(!x||a[x].l[0]>x2||a[x].r[0]<x1||a[x].l[1]>y2||a[x].r[1]<y1)return 0;
	if(x1<=a[x].l[0]&&a[x].r[0]<=x2&&y1<=a[x].l[1]&&a[x].r[1]<=y2)return a[x].sum;
	ll ret=0;
	if(x1<=a[x].p[0]&&a[x].p[0]<=x2&&y1<=a[x].p[1]&&a[x].p[1]<=y2)ret+=a[x].v;
	return ret+query(ls,x1,y1,x2,y2)+query(rs,x1,y1,x2,y2);
}
int main(){
	n=getll();
	while(233){
		ll op=getll();
		if(op==3)break;
		if(op==1){
			for(ll i=0;i<2;++i)
				nd.p[i]=getll()^ans;
			nd.v=getll()^ans;
			insert(root,0);
		}else {
			ll x1=getll()^ans,y1=getll()^ans,x2=getll()^ans,y2=getll()^ans;
			ans=query(root,x1,y1,x2,y2);
			cout<<ans<<'\n';
		}
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值