• 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
    ",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;
    }
    
  • 相关阅读:
    Windows 7的 磁盘管理中,某个磁盘或分区,突然变成只读。
    Python 静态变量 与 静态方法
    如何用手机上网给电信固话充值
    Windows,查看进程的连接的IP地址,批量模式,最后做成Excel
    如果在VMware上免费下载驱动
    DELL iDRAC 远程虚拟机报错:虚拟介质分离或所选虚拟磁盘驱动器的虚拟介质重定向已由另一用户使用
    Windows Server 2008安装 百度Wifi 360Wifi 小米Wifi 失败的解决方法
    让Windows 8 / 8.1 以及 Windows Server 2012 / 2012 R2的桌面,显示我的电脑图标
    让Windows 8 / 8.1 以及 Windows Server 2012 / 2012 R2的任务管理器的性能面板,显示磁盘数据
    企业CIO、CTO必读的34个经典故事
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/10660079.html
Copyright © 2020-2023  润新知