【USACO 2018 February Silver】Teleportation 题解

Easy subject:

Seeking \ (\ sum \ limits_ {i = 1} ^ n {\ min \ left \ {| a_i-b_i |, | a_i | + | y-b_i | \ right \}} \) minimum

Ideas

For each \ (y \) , consider \ (O (1) \) to calculate the answer.

We first calculate \ (\ sum | a_i-b_i | \) and convert the answer to the maximum value of "savings".

For a group of \ (a_i, b_i \) , if it passes through the portal, the end of the portal must be on a section with \ (b_i \) as the center point. At the same time, the distance that can be saved is reduced to both sides with \ (b_i \) as the center, that is:

Inkedfig_teleport_silver_feb18_LI.jpg

Next, we only need to find out how much is saved at \ (b_i \) to find the left and right endpoints.

There are two cases

  1. \ (| a_i | \ ge | a_i-b_i | \) There is no savings, the distance to the portal is greater than or equal to two points.

  2. \ (| a_i | <| a_i-b_i | \) saves \ (| a_i-b_i |-| a_i | \) which is the distance between two points minus the distance to the portal.

If it is the second case, then the left endpoint is: \ (b_i- | a_i-b_i | + | a_i | \)

右端点为:\(b_i+|a_i-b_i|-|a|\)

How much is saved by adding and subtracting the center point

The solution of USACO is divided into two cases, in fact, the absolute value is taken apart.

After getting the left, middle, and right endpoints, the slope of the left endpoint is reduced by 1, the slope of the middle endpoint is increased by 2 (think why), and the slope of the right endpoint is decreased by 1. When calculating the answer, use the difference method to get how much the "saving value" of the current point is increased from the previous point, and then count the answer.

achieve

When changing the slope, use a balanced tree (map), or discretization to solve the spatial problem. At the same time, we found that an endpoint must be able to get the answer (sensual understanding). Therefore, we can only save the endpoints, and use the slope times the distance to differentiate, that is, the statistical answer.

Code

#include<map>
#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
int n,a,b;
map<int,int>f;
long long ans;
void read(int &x){
	char c=getchar();
	for(;c<33;c=getchar());
	int f=1;
	if(c=='-'){
		f=-1;
		c=getchar();
	}
	for(x=0;(c>47)&&(c<58);x=x*10+c-48,c=getchar());
	x*=f;
}
int main(){
	freopen("teleport.in","r",stdin);
	freopen("teleport.out","w",stdout);
	read(n);
	for(int i=1;i<=n;i++){
		read(a);read(b);
		ans+=abs(a-b);
		if(abs(a)<=abs(a-b)){
			f[b]+=2;
			f[b-abs(a-b)+abs(a)]--;
			f[b+abs(a-b)-abs(a)]--;
		}
	}
	long long c=ans,s=0,l=-0x7fffffff;
	for(map<int,int>::iterator i=f.begin();i!=f.end();i++){
		int y=i->first,fx=i->second;
		c+=s*(y-l);
		l=y;
		s+=fx;
		ans=min(ans,c);
	}
	printf("%lld",ans);
	fclose(stdin);
	fclose(stdout);
}

Guess you like

Origin www.cnblogs.com/groundwater/p/12747675.html