zoukankan      html  css  js  c++  java
  • [BZOJ4066]简单题

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

    命令 参数限制 内容
    (1\,x\,y\,A) (1leqslant x,yleqslant N)(A)是正整数 将格子(x,y)里的数字加上(A)
    (2\,x_1\,y_1\,x_2\,y_2) (1leqslant x_1leqslant x_2leqslant N\1leqslant y_1leqslant y_2leqslant N) 输出(x_1\,y_1\,x_2\,y_2)这个矩形内的数字和
    (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
    (1leqslant Nleqslant500000),操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。


    20M显然不能树套树……于是我们用一个简单的数据结构——KD-Tree

    自信的写了一发,交上去TLE……一测数据发现极限数据跑了2m……

    完全不会优化啊……还是%%%hzwer

    定一个阀值,当KD-Tree插入操作达到这个阀值时,就暴力重构KD-Tree

    然后就可以过了……

    /*program from Wolfycz*/
    #include<cmath>
    #include<ctime>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline 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<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=2e5,V=1e4;
    int T;
    struct S1{
    	#define ls(p) tree[p].ls
    	#define rs(p) tree[p].rs
    	struct node{
    		int v[2],Max[2],Min[2];
    		int ls,rs,type,val,sum;
    		void insert(int type,int val){v[type]=Min[type]=Max[type]=val;}
    		bool operator <(const node &tis)const{return v[T]<tis.v[T];}
    	}tree[N+10];
    	int root,tot;
    	int L[2],R[2];
    	void Add(int *a,int v){a[0]=a[1]=v;}
    	void init(){Add(tree[0].Max,-inf),Add(tree[0].Min,inf);}
    	void updata(int p){
    		tree[p].Min[0]=min(tree[p].v[0],min(tree[ls(p)].Min[0],tree[rs(p)].Min[0]));
    		tree[p].Min[1]=min(tree[p].v[1],min(tree[ls(p)].Min[1],tree[rs(p)].Min[1]));
    		tree[p].Max[0]=max(tree[p].v[0],max(tree[ls(p)].Max[0],tree[rs(p)].Max[0]));
    		tree[p].Max[1]=max(tree[p].v[1],max(tree[ls(p)].Max[1],tree[rs(p)].Max[1]));
    	}
    	int rebuild(int l,int r,int type){
    		T=type;
    		int mid=(l+r)>>1,p=mid;
    		nth_element(tree+l,tree+mid,tree+r+1);
    		tree[p].type=type,tree[p].sum=0;
    		tree[p].ls=tree[p].rs=0;
    		if (l<mid)	ls(p)=rebuild(l,mid-1,type^1);
    		if (r>mid)	rs(p)=rebuild(mid+1,r,type^1);
    		updata(p);
    		tree[p].sum=tree[ls(p)].sum+tree[rs(p)].sum+tree[p].val;
    		return p;
    	}
    	void Modify(int &p,int x,int y,int v){
    		if (!p){
    			p=++tot;
    			tree[p].insert(0,x);
    			tree[p].insert(1,y);
    			tree[p].type=rand()&1;
    			tree[p].val=tree[p].sum=v;
    			return;
    		}
    		(tree[p].type?y:x)<tree[p].v[tree[p].type]?Modify(ls(p),x,y,v):Modify(rs(p),x,y,v);
    		updata(p),tree[p].sum=tree[ls(p)].sum+tree[p].val+tree[rs(p)].sum;
    	}
    	int Query(int p){
    		if (L[0] >tree[p].Max[0]||R[0] <tree[p].Min[0]||L[1] >tree[p].Max[1]||R[1] <tree[p].Min[1])	return 0;
    		if (L[0]<=tree[p].Min[0]&&tree[p].Max[0]<=R[0]&&L[1]<=tree[p].Min[1]&&tree[p].Max[1]<=R[1])	return tree[p].sum;
    		int res=0;
    		if (L[0]<=tree[p].v[0]&&tree[p].v[0]<=R[0]&&L[1]<=tree[p].v[1]&&tree[p].v[1]<=R[1])	res=tree[p].val;
    		res+=Query(ls(p))+Query(rs(p));
    		return res;
    	}
    	int Query(int x1,int y1,int x2,int y2){
    		L[0]=x1,R[0]=x2,L[1]=y1,R[1]=y2;
    		return Query(root);
    	}
    }KDT;//KD-Tree
    int main(){
    	srand(time(0));
    	int n=read(),cnt=0;
    	KDT.init();
    	for (int lastans=0;;){
    		int type=read();
    		if (type==1){
    			cnt++;
    			int x=read()^lastans,y=read()^lastans,v=read()^lastans;
    			KDT.Modify(KDT.root,x,y,v);
    			if (cnt%V==0)	KDT.root=KDT.rebuild(1,KDT.tot,0);
    		}
    		if (type==2){
    			int x1=read()^lastans,y1=read()^lastans,x2=read()^lastans,y2=read()^lastans;
    			printf("%d
    ",lastans=KDT.Query(x1,y1,x2,y2));
    		}
    		if (type==3)	break;
    	}
    	return 0;
    }
    
  • 相关阅读:
    OneSQL安装
    Dropbox可伸缩性设计最佳实践分享
    软件开发实践的24条军规
    最精彩的英语学习经验总结:俺的英语之路
    Facebook和Google如何激发工程师的创造力
    十种更好的表达“你的代码写的很烂”的方法
    一次java程序的重构
    漂亮代码
    一段代码引发的思考
    最难忘的Bug调试经历
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10284724.html
Copyright © 2011-2022 走看看