BZOJ4066: 简单题

BZOJ4066: 简单题

Description

你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:

 

命令

参数限制

内容

1 x y A

1<=x,y<=N,A是正整数

将格子x,y里的数字加上A

2 x1 y1 x2 y2

1<=x1<= x2<=N

1<=y1<= y2<=N

输出x1 y1 x2 y2这个矩形内的数字和

3

终止程序

 

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,保证答案在int范围内并且解码之后数据仍合法。

题解Here!

看完题二话不说一个树状数组$+Treap$。
然后就$MLE$了。。。
回头看题:怎么只有$20M$???
这。。。强制在线。。。只好$K-D\ Tree$。。。
其实有一道弱化版:

BZOJ1176: [Balkan2007]Mokia

但是这道题却只能用$K-D\ Tree$。。。

感觉$K-D\ Tree$要变成替罪羊树了。。。

还拍平重建。。。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 200010
#define MAX (1LL<<30)
#define Alpha 0.75
using namespace std;
int n,m;
int root,size=0,l1,r1,l2,r2;
int top,recycle[MAXN];
bool sort_flag=false;
struct Point{
	int x,y,z;
	friend bool operator <(const Point &p,const Point &q){
		if(sort_flag)return p.y<q.y;
		return p.x<q.x;
	}
}point[MAXN],now;
struct Tree{
	Point point;
	int maxx,maxy,minx,miny,val,sum,size,lson,rson;
}a[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline bool check_inside(int x1,int y1,int x2,int y2){
	return ((l1<=x1&&x2<=l2)&&(r1<=y1&&y2<=r2));
}
inline bool check_outside(int x1,int y1,int x2,int y2){
	return ((x2<l1||x1>l2)||(y2<r1||y1>r2));
}
inline int newnode(const Point &p){
	int rt;
	if(top)rt=recycle[top--];
	else rt=++size;
	a[rt].point=p;
	a[rt].maxx=a[rt].minx=p.x;
	a[rt].maxy=a[rt].miny=p.y;
	a[rt].val=a[rt].sum=p.z;
	a[rt].lson=a[rt].rson=0;
	a[rt].size=1;
	return rt;
}
inline void pushup(int rt){
	int lson=a[rt].lson,rson=a[rt].rson;
	a[rt].size=a[lson].size+a[rson].size+1;
	a[rt].sum=a[lson].sum+a[rson].sum+a[rt].val;
	a[rt].maxx=max(a[rt].maxx,max(a[lson].maxx,a[rson].maxx));
	a[rt].maxy=max(a[rt].maxy,max(a[lson].maxy,a[rson].maxy));
	a[rt].minx=min(a[rt].minx,min(a[lson].minx,a[rson].minx));
	a[rt].miny=min(a[rt].miny,min(a[lson].miny,a[rson].miny));
}
void buildtree(int l,int r,int &rt,int flag){
	int mid=l+r>>1;
	sort_flag=flag;
	nth_element(point+l,point+mid,point+r+1);
	rt=newnode(point[mid]);
	if(l<mid)buildtree(l,mid-1,a[rt].lson,flag^1);
	if(mid<r)buildtree(mid+1,r,a[rt].rson,flag^1);
	pushup(rt);
}
void pia(int rt,int num){
	if(a[rt].lson)pia(a[rt].lson,num);
	point[num+a[a[rt].lson].size+1]=a[rt].point;
	recycle[++top]=rt;
	if(a[rt].rson)pia(a[rt].rson,num+a[a[rt].lson].size+1);
}
inline void check(int &rt,int flag){
	if(Alpha*a[rt].size<max(a[a[rt].lson].size,a[a[rt].rson].size)){
		pia(rt,0);
		buildtree(1,a[rt].size,rt,flag);
	}
}
void insert(int &rt,int flag){
	if(!rt){
		rt=newnode(now);
		return;
	}
	sort_flag=flag;
	if(a[rt].point<now)insert(a[rt].rson,flag^1);
	else insert(a[rt].lson,flag^1);
	pushup(rt);
	check(rt,flag);
}
int query(int rt){
	if(check_inside(a[rt].minx,a[rt].miny,a[rt].maxx,a[rt].maxy))return a[rt].sum;
	if(check_outside(a[rt].minx,a[rt].miny,a[rt].maxx,a[rt].maxy))return 0;
	int ans=0;
	if(check_inside(a[rt].point.x,a[rt].point.y,a[rt].point.x,a[rt].point.y))ans+=a[rt].val;
	if(a[rt].lson)ans+=query(a[rt].lson);
	if(a[rt].rson)ans+=query(a[rt].rson);
	return ans;
}
void work(){
	int f,last=0;
	while(1){
		f=read();
		if(f==3)return;
		if(f==1){
			now.x=read()^last;now.y=read()^last;now.z=read()^last;
			insert(root,0);
		}
		else{
			l1=read()^last;r1=read()^last;l2=read()^last;r2=read()^last;
			last=query(root);
			printf("%d\n",last);
		}
	}
}
void init(){
	n=read();
	a[0].maxx=a[0].maxy=-MAX;
	a[0].minx=a[0].miny=MAX;
}
int main(){
	init();
	work();
	return 0;
}

 

posted @ 2019-04-05 21:45  符拉迪沃斯托克  阅读(43)  评论(0编辑  收藏
Live2D