zoukankan      html  css  js  c++  java
  • BZOJ_4066_简单题_KDtree

    BZOJ_4066_简单题_KDtree

    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范围内并且解码之后数据仍合法。

    离线可以CDQ分治做。
    这题强制在线,那么用KDTree处理矩形查询问题。
    每个节点维护矩形点权和即可,查询时如果当前矩形被包含了就返回这个值,然后递归左右子树。
    插入点数太多会导致KDTree的结构退化,于是需要重构。
     
    代码:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 200050
    #define FAC 0.75
    #define ls ch[p][0]
    #define rs ch[p][1]
    #define _max(x,y) ((x)>(y)?(x):(y))
    #define _min(x,y) ((x)<(y)?(x):(y))
    int ch[N][2],sum[N],mx[N][2],mn[N][2],now,root,dep[N],n;
    struct Point {
    	int p[2],v;
    	bool operator < (const Point &x) const {
    		return p[now]==x.p[now]?p[!now]<x.p[!now]:p[now]<x.p[now];
    	}
    }a[N];
    inline char nc() {
    	static char buf[100000],*p1,*p2;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    int rd() {
    	int x=0; char s=nc();
    	while(s<'0'||s>'9') s=nc();
    	while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
    	return x;
    }
    void pushup(int p,int x) {
    	mx[p][0]=_max(mx[p][0],mx[x][0]);
    	mn[p][0]=_min(mn[p][0],mn[x][0]);
    	mx[p][1]=_max(mx[p][1],mx[x][1]);
    	mn[p][1]=_min(mn[p][1],mn[x][1]);
    	sum[p]+=sum[x];
    }
    int build(int l,int r,int type) {
    	int mid=(l+r)>>1; now=type;
    	nth_element(a+l,a+mid,a+r+1);
    	mx[mid][0]=mn[mid][0]=a[mid].p[0];
    	mx[mid][1]=mn[mid][1]=a[mid].p[1];
    	sum[mid]=a[mid].v;
    	ch[mid][0]=ch[mid][1]=0;
    	if(l<mid) ch[mid][0]=build(l,mid-1,!type),pushup(mid,ch[mid][0]);
    	if(r>mid) ch[mid][1]=build(mid+1,r,!type),pushup(mid,ch[mid][1]);
    	return mid;
    }
    void insert(int x) {
    	int p=root;
    	mx[x][0]=mn[x][0]=a[x].p[0];
    	mx[x][1]=mn[x][1]=a[x].p[1];
    	sum[x]=a[x].v;
    	if(!p) {root=x; return ;}
    	now=0;
    	while(1) {
    		pushup(p,x);
    		if(a[x]<a[p]) {
    			if(ls) p=ls;
    			else {ls=x; return ;}
    		}else {
    			if(rs) p=rs;
    			else {rs=x; return ;}
    		}
    		now^=1;
    	}
    }
    int query(int x,int y,int z,int w,int p) {
    	if(mn[p][0]>=x&&mx[p][0]<=z&&mn[p][1]>=y&&mx[p][1]<=w) return sum[p];
    	int re=0;
    	if(a[p].p[0]<=z&&a[p].p[0]>=x&&a[p].p[1]<=w&&a[p].p[1]>=y) re+=a[p].v;
    	if(ls&&mn[ls][0]<=z&&mx[ls][0]>=x&&mn[ls][1]<=w&&mx[ls][1]>=y) re+=query(x,y,z,w,ls);
    	if(rs&&mn[rs][0]<=z&&mx[rs][0]>=x&&mn[rs][1]<=w&&mx[rs][1]>=y) re+=query(x,y,z,w,rs);
    	return re;
    }
    int main() {
    	rd();
    	int opt,x,y,z,w,ans=0;
    	while(1) {
    		opt=rd();
    		if(opt==3) break;
    		if(opt==1) {
    			n++;
    			x=rd(); y=rd(); z=rd();
    			a[n].p[0]=x^ans;
    			a[n].p[1]=y^ans;
    			a[n].v=z^ans;
    			insert(n);
    			if(n%10000==0) root=build(1,n,0);
    		}else {
    			x=rd(); y=rd(); z=rd(); w=rd();
    			x^=ans; y^=ans; z^=ans; w^=ans;
    			printf("%d
    ",ans=query(x,y,z,w,root));
    		}
    	}
    }
    
  • 相关阅读:
    ios version和build
    协议
    masonry
    加密
    coredata
    随机附魔笔记
    Mac下搭建AzerothCore遇到的坑
    cocospods 私服搭建
    网络营销工具
    WKWebView不能重定向打开新界面,解决办法
  • 原文地址:https://www.cnblogs.com/suika/p/9279096.html
Copyright © 2011-2022 走看看