zoukankan      html  css  js  c++  java
  • Jzoj3591 数据

    现在,二维平面上有N个点。Alex 需要实现以下三种操作:

    1. 在点集里添加一个点;

    2. 给出一个点,查询它到点集里所有点的曼哈顿距离的最小值;

    3. 给出一个点,查询它到点集里所有点的曼哈顿距离的最大值。 

    两个点的曼哈顿距离定义为它们的横坐标差的绝对值与纵坐标差的绝对值的和。这么困难的问题,Alex当然不会做,只好再次请你帮忙了。


    树套树裸题

    cdq分治第二题诶,突然才感觉cdq分治好棒啊

    分成按照相对询问的坐标四种情况,分别是1234象限,让后分别开两颗线段树分治

    注意这样会超时,我们按照x分治,将23象限分到一起分治,14象限分到一起分治,同时开4颗动态开点的线段树以y坐标作为键值,这样可以减小常数,同时也减小代码量

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<queue> 
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 100010
    #define M 1000000000
    #define mid (l+r>>1)
    #define LL long long
    using namespace std;
    int n,m,t=0; LL ans[N];
    struct op{ int o,x,y,r; } s[N<<1],c[N<<1],r[N<<1];
    struct seg{
    	int rt,cnt;
    	struct tree{ int l,r; LL s,m; } s[N<<5];
    	void clear(){ cnt=rt=0; }
    	inline void insert(int l,int r,int& x,int p,LL k){
    		if(!x) s[x=++cnt]=(tree){0,0,-(M<<1),M<<1}; 
    		s[x].s=max(s[x].s,k); s[x].m=min(s[x].m,k);
    		if(l==r) return; 
    		if(p<=mid) insert(l,mid,s[x].l,p,k);
    			else insert(mid+1,r,s[x].r,p,k);
    	}
    	inline LL query(int l,int r,int x,int L,int R){
    		if(!x) return -(M<<1);
    		if(L<=l && r<=R) return s[x].s;
    		LL ans=-(M<<1);
    		if(L<=mid) ans=max(ans,query(l,mid,s[x].l,L,R));
    		if(mid<R) ans=max(ans,query(mid+1,r,s[x].r,L,R));
    		return ans;
    	}
    	inline LL Query(int l,int r,int x,int L,int R){
    		if(!x) return M<<1;
    		if(L<=l && r<=R) return s[x].m;
    		LL ans=M<<1;
    		if(L<=mid) ans=min(ans,Query(l,mid,s[x].l,L,R));
    		if(mid<R) ans=min(ans,Query(mid+1,r,s[x].r,L,R));
    		return ans;
    	}
    	inline void insert(int p,int k){ insert(0,M,rt,p,k); }
    	inline LL query(int L,int R){ return query(0,M,rt,L,R); }
    	inline LL Query(int L,int R){ return Query(0,M,rt,L,R); }
    }MX,MS;
    void cdq1(int l,int r){
    	if(l==r) return;
    	int m=mid,t=l,i,j;
    	cdq1(l,m); cdq1(m+1,r);
    	MX.clear(); 
    	MS.clear();
    	for(i=l,j=m+1;i<=m&&j<=r;)
    		if(s[i].x>=s[j].x){
    			if(s[i].o==0){
    				MX.insert(s[i].y,s[i].x+s[i].y);	
    				MS.insert(s[i].y,s[i].x-s[i].y);
    			}
    			c[t++]=s[i++];
    		} else{
    			if(s[j].o==1) ans[s[j].r]=min(ans[s[j].r],min(MX.Query(s[j].y,M)-s[j].x-s[j].y,MS.Query(0,s[j].y)-s[j].x+s[j].y));
    				else if(s[j].o==2) ans[s[j].r]=max(ans[s[j].r],max(MX.query(s[j].y,M)-s[j].x-s[j].y,MS.query(0,s[j].y)-s[j].x+s[j].y));
    			c[t++]=s[j++];
    		}
    	for(;i<=m;++i) c[t++]=s[i];
    	for(;j<=r;++j){
    			if(s[j].o==1) ans[s[j].r]=min(ans[s[j].r],min(MX.Query(s[j].y,M)-s[j].x-s[j].y,MS.Query(0,s[j].y)-s[j].x+s[j].y));
    				else if(s[j].o==2) ans[s[j].r]=max(ans[s[j].r],max(MX.query(s[j].y,M)-s[j].x-s[j].y,MS.query(0,s[j].y)-s[j].x+s[j].y));
    			c[t++]=s[j];
    	}
    	for(int i=l;i<=r;++i) s[i]=c[i];
    }
    void cdq2(int l,int r){
    	if(l==r) return;
    	int m=mid,t=l,i,j;
    	cdq2(l,m); cdq2(m+1,r); 
    	MX.clear();
    	MS.clear(); 
    	for(i=l,j=m+1;i<=m&&j<=r;)
    		if(s[i].x<=s[j].x){
    			if(s[i].o==0){
    				MX.insert(s[i].y,s[i].x+s[i].y);
    				MS.insert(s[i].y,-s[i].x+s[i].y);
    			}
    			c[t++]=s[i++];
    		} else{
    			if(s[j].o==1) ans[s[j].r]=min(ans[s[j].r],min(-MX.query(0,s[j].y)+s[j].x+s[j].y,MS.Query(s[j].y,M)+s[j].x-s[j].y));
    				else if(s[j].o==2) ans[s[j].r]=max(ans[s[j].r],max(-MX.Query(0,s[j].y)+s[j].x+s[j].y,MS.query(s[j].y,M)+s[j].x-s[j].y));
    			c[t++]=s[j++];
    		}
    	for(;i<=m;++i) c[t++]=s[i];
    	for(;j<=r;++j){
    			if(s[j].o==1) ans[s[j].r]=min(ans[s[j].r],min(-MX.query(0,s[j].y)+s[j].x+s[j].y,MS.Query(s[j].y,M)+s[j].x-s[j].y));
    				else if(s[j].o==2) ans[s[j].r]=max(ans[s[j].r],max(-MX.Query(0,s[j].y)+s[j].x+s[j].y,MS.query(s[j].y,M)+s[j].x-s[j].y));
    			c[t++]=s[j];
    		}
    	for(int i=l;i<=r;++i) s[i]=c[i]; 
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%d%d",&s[i].x,&s[i].y);
    	scanf("%d",&m);
    	for(int i=1;i<=m;++i){
    		scanf("%d%d%d",&s[i+n].o,&s[i+n].x,&s[i+n].y);
    		if(s[i+n].o) s[i+n].r=++t,ans[t]=(s[i+n].o&1?M<<1:0);
    	}
    	memcpy(r,s,sizeof s); cdq1(1,n+m);
    	memcpy(s,r,sizeof s); cdq2(1,n+m);
    	for(int i=1;i<=t;++i) printf("%lld
    ",ans[i]);
    }



  • 相关阅读:
    Firefox页面截图插件Pearl Crescent Page Saver
    Effective C++ (5) 几个关于数组的问题
    Notice
    Effective C++ (4) c++中的命名空间
    Effective C++ (7) 强制类型转换
    Effective C++ (3) 避免C++头文件的多重包含
    Effective C++ (2) C#中的Const和Readonly
    总结一下这段时间的生活
    如何让rose一开始的那个向导对话框出现?
    Effective C++ (8) 顺序容器vector,list,deque
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/8449240.html
Copyright © 2011-2022 走看看