zoukankan      html  css  js  c++  java
  • jzoj2866. 【集训队互测 2012】Bomb

    Description

    A 国和 B 国是两个超级大国,长期处于冷战状态;
    A 国在 B 国中设有 N 个情报站,编号为 1,2,3, …… ,N ,每个情报站有一个坐标 (Xi,Yi) 。但是, A 国的工作人员发现,每个情报站里都被埋上了炸弹!
    这些炸弹非常特殊 , 只要同时拆除其中的三个炸弹 , 所有炸弹就都不会爆炸了。
    由于各个情报站联络需要代价 , 拆除炸弹需要花费的总代价为这些炸弹两两之间的曼哈顿距离和。
    现在 A 国的指挥部门找到了你 , 希望知道可能需要的最大代价和最小代价 。

    Input

    输入的第一行包含一个整数 N 。接下来 N 行,第 i+1 行两个整数 Xi,Yi ,表示第 i 个情报站的坐标。

    Output

    输出两行 , 每行包含一个整数 , 第一行表示可能的最大代价 , 第二行表示可能的最小代价。

    Sample Input

    4
    1 1
    1 2
    2 1
    2 3

    Sample Output

    6
    4

    Data Constraint

    对于 30% 的数据, N<=500
    对于另外 10% 的数据,每个点出现至少两遍
    对于 50% 的数据, N<=1000
    对于 60% 的数据, N<=8000
    对于 70% 的数据, N<=15000
    对于 80% 的数据, N<=50000
    对于 100% 的数据, N<=100000 , 0<=Xi,Yi<=10^8

    Hint

    对于两个点 (X0,Y0),(X1,Y1) ,
    它们之间的曼哈顿距离为 abs(X0-X1)+abs(Y0-Y1) 。

    赛时

    这道题比较奇妙。
    一开始我还以为是什么计算几何神仙题。
    结果推一推发现不是。
    无脑选手++
    最后交了个30分暴力滚粗。

    题解

    话说这道题数据有点水,可以利用(n^2)卡到90分。
    然后利用分段打表两者相结合就过了。
    无话可说

    100%
    我们首先考虑最大值怎么求:
    我们发现,一个点对答案做出贡当且仅当其作为Xmin,Xmax,Ymin,Ymax出现才行。
    然后贪心做即可。

    然后就是最小值怎么求:
    我们首先把整个图形旋转90旋转4次,每次就会出现以下两种情况可能对答案有贡献:
    在这里插入图片描述
    在这里插入图片描述
    对于第一种,我们直接枚举中间的点,然后找出其右上方向离它最近的点,和左下方向离它最近的点。
    更新答案即可。
    但是一定要注意到重复出现的点。

    对于第二种,做法就比较神奇了。
    我们看到上图,可以发现,最左下的点提供Xmin,Ymin
    最上面的点提供Ymax,最右边的点提供Xmax。
    那么我们只需要快速求出后面两个即可。

    考虑扫描线,首先当然是离散化y轴啦~
    我们考虑从右往左边扫。
    在这个y轴建立一个线段树,线段树上每个点记录的是:
    x:当前行到扫到的列最近的点的x坐标。
    y:在当前行上距离当前行最近的点的y坐标。
    ans:当前点作为最右边的点的答案。
    那么每次扫到一个点(xi,yi),我们就在线段树上求出它上面的点中答案最小的点。
    然后更新。
    首先,把当前点所在的行的x更新成xi
    然后把当前点下面的行的y都打上lazy标记。
    每次下传标记时我们就判断lazy标记是否能更新y值(lazy<y)同时更新ans即可。
    实现起来细节还是比较多的(尤其是标记下传)

    标程

    小细节真™多。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    struct node
    {
    	long long xmin,ymin,ans;
    };
    
    int n;
    long long maxans,minans,ans,pp;
    long long x[100010],y[100010],ny[100010],id[100010];
    long long lazy[400010],t[400010],op[100010][5],gb[400010],xx[100010],yy[100010];
    node tree[400010],gbt[400010];
    
    int abs(int x)
    {
    	if (x<0) return -x;
    	else return x;
    }
    
    void qsort(int l,int r)
    {
    	int i=l;int j=r;
    	int m=xx[(i+j)/2];
    	int m1=yy[(i+j)/2];
    	int m2=id[(i+j)/2];
    	while (i<=j)
    	{
    		while ((xx[i]>m)||(xx[i]==m && yy[i]>m1)||(xx[i]==m && yy[i]==m1 && ((pp==0 && id[i]>m2)||(pp==1 && id[i]<m2)))) i++;
    		while ((xx[j]<m)||(xx[j]==m && yy[j]<m1)||(xx[j]==m && yy[j]==m1 && ((pp==0 && id[j]<m2)||(pp==1 && id[j]>m2)))) j--;
    		if (i<=j)
    		{
    			swap(xx[i],xx[j]);
    			swap(yy[i],yy[j]);
    			swap(ny[i],ny[j]);
    			swap(id[i],id[j]);
    			i++;j--;
    		}
    	}
    	if (l<j) qsort(l,j);
    	if (r>i) qsort(i,r); 
    }
    
    void qsorty(int l,int r)
    {
    	int i=l;int j=r;
    	int m=yy[(i+j)/2];
    	while (i<=j)
    	{
    		while (yy[i]<m) i++;
    		while (yy[j]>m) j--;
    		if (i<=j)
    		{
    			swap(yy[i],yy[j]);
    			swap(xx[i],xx[j]);
    			swap(id[i],id[j]);
    			i++;j--;
    		}
    	}
    	if (l<j) qsorty(l,j);
    	if (r>i) qsorty(i,r); 
    }
    
    void lazy_down(int x)
    {
    	tree[x*2].ymin=min(tree[x*2].ymin,lazy[x]);
    	tree[x*2+1].ymin=min(tree[x*2+1].ymin,lazy[x]);
    	lazy[x*2]=min(lazy[x*2],lazy[x]);
    	lazy[x*2+1]=min(lazy[x*2+1],lazy[x]);
    	tree[x*2].ans=min(tree[x*2].ans,tree[x*2].xmin+lazy[x]); 
    	tree[x*2+1].ans=min(tree[x*2+1].ans,tree[x*2+1].xmin+lazy[x]);
    	lazy[x]=1000000000;
    }
    
    void queryall(int x,int l,int r,int st,int en)
    {
    	if (l==st && r==en)
    	{
    		ans=min(ans,tree[x].ans);
    	}
    	else
    	{
    		int mid=(l+r)/2;
    		lazy_down(x);
    		if (en<=mid) queryall(2*x,l,mid,st,en);
    		else if (st>mid) queryall(2*x+1,mid+1,r,st,en);
    		else
    		{
    			queryall(2*x,l,mid,st,mid);
    			queryall(2*x+1,mid+1,r,mid+1,en);
    		}		
    	}
    }
    
    void find(int x,int l,int r,int st,int en)
    {
    	if (l==st && r==en)
    	{
    		ans=min(ans,t[x]);
    	}
    	else
    	{
    		int mid=(l+r)/2;
    		if (en<=mid) find(2*x,l,mid,st,en);
    		else if (st>mid) find(2*x+1,mid+1,r,st,en);
    		else
    		{
    			find(2*x,l,mid,st,mid);
    			find(2*x+1,mid+1,r,mid+1,en);
    		}		
    	}
    }
    
    void change(int x,int l,int r,int st,int en)
    {
    	if (l==r)
    	{
    		t[x]=en;
    	}
    	else
    	{
    		int mid=(l+r)/2;
    		if (st<=mid) change(2*x,l,mid,st,en);
    		else if (st>mid) change(2*x+1,mid+1,r,st,en);	
    		t[x]=min(t[2*x],t[2*x+1]);
    	}
    }
    
    void modifyx(int x,int l,int r,int st,int en)
    {
    	if (l==r)
    	{
    		tree[x].xmin=en;
    	}
    	else
    	{
    		int mid=(l+r)/2;
    		lazy_down(x);
    		if (st<=mid) modifyx(2*x,l,mid,st,en);
    		else if (st>mid) modifyx(2*x+1,mid+1,r,st,en);	
    		tree[x].xmin=min(tree[2*x].xmin,tree[2*x+1].xmin);
    	}
    }
    
    void modifyy(int x,int l,int r,int st,int en,long long op)
    {
    	if (l==st && r==en)
    	{
    		if (tree[x].ymin>op)
    		{
    			tree[x].ymin=op;
    		}		
    		lazy[x]=min(lazy[x],op);
    		tree[x].ans=min(tree[x].ans,tree[x].xmin+op);
    	}
    	else
    	{
    		int mid=(l+r)/2;
    		lazy_down(x);
    		if (en<=mid) modifyy(2*x,l,mid,st,en,op);
    		else if (st>mid) modifyy(2*x+1,mid+1,r,st,en,op);
    		else
    		{
    			modifyy(2*x,l,mid,st,mid,op);
    			modifyy(2*x+1,mid+1,r,mid+1,en,op);
    		}	
    		tree[x].ymin=min(tree[2*x].ymin,tree[2*x+1].ymin);
    		tree[x].ans=min(tree[2*x].ans,tree[2*x+1].ans);	
    	}
    }
    
    void find_min(int now)
    {
    	for (int i=1;i<=n;i++)
    	{
    		id[i]=i;
    	}
    	qsorty(1,n);
    	int j=1;
    	ny[1]=1;
    	for (int i=2;i<=n;i++)
    	{
    		if (yy[i]!=yy[i-1])
    		{
    			j++;
    		}
    		ny[i]=j;
    	}
    	int zd=j;
    	qsort(1,n);
    	memcpy(tree,gbt,sizeof(gbt));
    	memcpy(lazy,gb,sizeof(gb));
    	memcpy(t,gb,sizeof(gb));
    	for (int i=1;i<=n;i++)
    	{
    		ans=1000000000;
    		find(1,1,zd,ny[i],zd);
    		op[id[i]][now]=min(op[id[i]][now],ans-xx[i]-yy[i]);
    		change(1,1,zd,ny[i],xx[i]+yy[i]);
    		ans=1000000000;
    		if (i>=3)
    		if (ny[i]<zd)
    		queryall(1,1,zd,ny[i]+1,zd);
    		minans=min(minans,ans-xx[i]-yy[i]);
    		modifyx(1,1,zd,ny[i],xx[i]);
    		if (ny[i]>1)
    		modifyy(1,1,zd,1,ny[i]-1,yy[i]);
    	}
    }
    
    void find_max()
    {
    	long long xmin=1000000000;
    	long long ymin=1000000000;
    	long long xmax=-1000000000;
    	long long ymax=-1000000000;
    	for (int i=1;i<=n;i++)
    	{
    		xmin=min(xmin,xx[i]);
    		xmax=max(xmax,xx[i]);
    		ymin=min(ymin,yy[i]);
    		ymax=max(ymax,yy[i]);
    	}
    	for (int i=1;i<=n;i++)
    	{
    		maxans=max(maxans,2*(max(xx[i]-xmin,xmax-xx[i])+max(yy[i]-ymin,ymax-yy[i])));
    	}
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d%d",&x[i],&y[i]);
    	}
    	maxans=-1000000000;
    	minans=1000000000;
    	for (int i=0;i<400000;i++) gb[i]=1000000000;
    	for (int i=0;i<400000;i++)
    	{
    		gbt[i].ans=1000000000;
    		gbt[i].xmin=1000000000;
    		gbt[i].ymin=1000000000;
    	}
    	memset(op,127,sizeof(op));
    	memcpy(xx,x,sizeof(x));
    	memcpy(yy,y,sizeof(y));
    	find_max();
    	for (int i=1;i<=4;i++)
    	{
    		memcpy(xx,x,sizeof(x));
    		memcpy(yy,y,sizeof(y));
    		if (i==1) find_min(i);
    		else if (i==2)
    		{
    			for (int j=1;j<=n;j++)
    			{
    				swap(xx[j],yy[j]);
    				yy[j]+=100000000;
    				xx[j]=100000000-xx[j];
    			}
    			find_min(i);
    		}
    		else
    		if (i==3)
    		{
    			pp++;
    			for (int j=1;j<=n;j++)
    			{
    				xx[j]=6-xx[j];
    				yy[j]=6-yy[j];
    			}
    			find_min(i);
    		}
    		else
    		{
    			for (int j=1;j<=n;j++)
    			{
    				swap(xx[j],yy[j]);
    				yy[j]=100000000-yy[j];
    				xx[j]+=100000000;
    			}
    			find_min(i);
    		}
    	}
    	for (int i=1;i<=n;i++)
    	{
    		minans=min(minans,op[i][1]+op[i][3]);
    		minans=min(minans,op[i][2]+op[i][4]);
    	}
    	printf("%d
    ",maxans);
    	printf("%d
    ",minans*2);
    }
    
    
  • 相关阅读:
    android studio中timber的配置
    bufferknife框架的正确使用方式 -终于他么知道了
    开源的图像滤镜库----for Android
    HSV做通道分离是出现的Vector内存越界错误
    HSV与RGB的相互转换的公式
    Windows下python的第三方库的安装
    Python出现"Non-ASCII character 'xe6' in file"错误解决方法
    Verilog的IDE Quartus II
    Java-ZipUtil工具类
    Java-JDBCUtil工具类
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11294112.html
Copyright © 2011-2022 走看看