标题:区间移位



标题:区间移位


数轴上有n个闭区间:D1,...,Dn。
其中区间Di用一对整数[ai, bi]来描述,满足ai < bi。
已知这些区间的长度之和至少有10000。
所以,通过适当的移动这些区间,你总可以使得他们的“并”覆盖[0, 10000]——也就是说[0, 10000]这个区间内的每一个点都落于至少一个区间内。
你希望找一个移动方法,使得位移差最大的那个区间的位移量最小。


具体来说,假设你将Di移动到[ai+ci, bi+ci]这个位置。你希望使得maxi{|ci|} 最小。


【输入格式】
输入的第一行包含一个整数n,表示区间的数量。
接下来有n行,每行2个整数ai, bi,以一个空格分开,表示区间[ai, bi]。
保证区间的长度之和至少是10000。


【输出格式】
输出一个数字,表示答案。如果答案是整数,只输出整数部分。如果答案不是整数,输出时四舍五入保留一位小数。


【样例输入】
2
10 5010
4980 9980


【样例输出】
20


【样例说明】
第一个区间往左移动10;第二个区间往右移动20。


【样例输入】
4
0 4000
3000 5000
5001 8000
7000 10000
【样例输出】
0.5
【样例说明】
第2个区间往右移0.5;第3个区间往左移0.5即可。


【数据规模与约定】
对于30%的评测用例,1 <= n <= 10;
对于100%的评测用例,1 <= n <= 10000,0 <= ai < bi <= 10000。


资源约定:
峰值内存消耗 < 256M
CPU消耗  < 2000ms




请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。


所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。

注意:主类的名字必须是:Main,否则按无效代码处理。

直接暴力的;就是先把区间存进去,然后根据左区间排序,然后遍历集合list里的所有区间,每次都最优覆盖区间,然后取那个区间移位最大的值,注意要特判第一个和最后一个,然后就好啦;

import java.util.*;
public class Main {
	static double eps = 1e-8;
	static Scanner in = new Scanner(System.in);
	static int t;
	static Comparator<point> cmp = new Comparator<point>() {
		@Override
		public int compare(point a, point b) {
			if (a.x != b.x) return a.x - b.x;
			else return a.y - b.y;
		}
	};
	public static void main(String[] args) {
		t = in.nextInt();
		solve();
	}
	private static void solve() {
		ArrayList<point> list = new ArrayList<point>();
		while (t-- != 0) {
			int a = in.nextInt();
			int b = in.nextInt();
			list.add(new point(a, b));
		}
		Collections.sort(list, cmp);
		//check
//		for (int i = 0; i < list.size(); i++) {
//			System.out.println(list.get(i).x + " " + list.get(i).y);
//		}
		solveAgain(list);
	}
	private static void solveAgain(ArrayList<point> list) {
		int max1 = 0;
		double max2 = 0;
		//如果排序后的第一个点的左区间点不是0,那么通过移动第一个让它变成0
		if (list.size() > 0 && list.get(0).x != 0) {
			int a = 0;
			int b = list.get(0).y - list.get(0).x;
			max1 = list.get(0).x;
			list.remove(0);
			list.add(0, new point(a, b));
		}
		
		//排序第一个后面的所有的点,每次进行比较
		for (int i = 1; i < list.size(); i++) {
			int cat = list.get(i).x - list.get(i - 1).y;
			if (cat <= 0) continue;//如果两个相差小于等于0,说明不需要通过移动来覆盖区间
			else {
 				if (i - 1 == 0) {//如果当前这个的前一个是第一个点,那么直接移动相差的距离
					max1 = Math.max(max1, cat);
				}//如果不是,那么就需要比较一下当前这个点a的前一个点b,看看b这个点的前一个和b这个点的后一个点的情况
				else {// -----------------------------------------
					double tmp = (double)(cat*1.0/2.0);//需要移动距离的一半
					//debug
//					System.out.println(tmp);
					double cat2 = (double)(list.get(i - 2).y - list.get(i - 1).x) - tmp;
					if (cat2 >= eps) {//如果可以移动一半距离的话,就移动一半
						max2 = Math.max(max2, tmp);
					} else {
						double cas = cat - cat2;
						max2 = Math.max(max2, Math.max(cas, cat2));
					}
				}
			}
		}
		//再看最后一个y是不是大于等于10000
		int checkfinal = list.get(list.size()-1).y;
		if (checkfinal < 10000) max1 = Math.max(max1, (10000 - checkfinal));
		if ((double)(1.0*max1) - max2 >= eps) {
			System.out.println(max1);
		} else {
			System.out.println(max2);
		}
	}
	static class point {
		int x, y;
		point() {}
		point(int x, int y) {
			this.x = x;
			this.y = y;
		}
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + x;
			result = prime * result + y;
			return result;
		}
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			point other = (point) obj;
			if (x != other.x)
				return false;
			if (y != other.y)
				return false;
			return true;
		}
		
	}
}



猜你喜欢

转载自blog.csdn.net/qq_34649947/article/details/80223708