codeforces #300 C. Tourist's Notes

题目大意:

每个地方都有一个高度Hi, 一个人从1号位置走到n号位置。 他希望走的路很平, 所以走过的所有相邻,高度差小于等于1。(按照1,2,3,4,5的顺序走)


也就是高度序列可以是 0 1 2 3 2 1 2 3 2 1 0 但是不可能0 1 2 5 3 2 1 (2到5,超过1了,5到3也超过1)



现在告诉你,他从1号走到n号位置, 然后给出其中m个位置的高度,求可能的最高高度。


我描述的题目意思好烂啊。。



换个方法描述:


有一个序列,相邻2个数字差的绝对值小于等于1。   现在给出这个序列长度为n, 然后告诉你序列中m个位置的数字。现在问你,满足条件的所有序列中,最大的元素是多少(一个序列由n个元素组成,问你数字最大的元素是几)。


无解输出IMPOSSIBLE


题解:

二分答案。

分解子问题:

假设知道i位置的值是x, j位置的值是y。

对于ai,ai+1,ai+2....aj这个序列中,最大的值可能是多少。

显然x,y交换并不影响答案。 所以我们令x<=y


首先判定是否有解,令cha = j-i

那么有解必须满足x+cha>=y才行。


然后二分答案, 2 * mid - cha - x <= y 的话,为可行解。 调整下限,否则调整上限。 (这个2 * mid - cha -x <= y挺容易想的啊…… 是化简过的式子。。自己推一下就行了)


坑爹点1: 答案上限是1.5 * 1e8而不是1e8……

坑爹点2:考虑最高的点是1号或者n号位置~ 




import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main
{
	static int n, m;
	static InputReader reader = new InputReader();
	static int a[] = new int[100200], b[] = new int[100200];
	public static void main(String args[])	throws IOException
	{
		n = reader.nextInt();
		m = reader.nextInt();
		doit();

		
	}
	
	public static int cal(int cha, int x, int y)
	//-1 无解,其他为最大解
	{
		if (x>y)	
		{
			int tmp= x;
			x=y;
			y=tmp;
		}
		if (x+cha < y)	return -1;
		int L = y, R = 200000001, mid;
		while (L + 1 < R)
		{
			mid = (L+R)/2;
			if (2 * mid - cha - x <= y)	L = mid;
			else R = mid;
		}
		return L;
	}
	
	public static void doit()	throws IOException
	{
		int ans = 0;
		a[0] = reader.nextInt();
		b[0] = reader.nextInt();
		for (int i = 1; i != m; ++ i)
		{
			a[i] = reader.nextInt();
			b[i] = reader.nextInt();
			int tmp = cal(a[i]-a[i-1], b[i-1], b[i]);
			if (tmp == -1)	//无解	
			{
				System.out.println("IMPOSSIBLE");
				return;
			}
			if (tmp > ans)	ans = tmp;
		}
		int tmp = a[0]-1 + b[0];
		if (tmp > ans)	ans = tmp;
		tmp = n-a[m-1] + b[m-1];
		if (tmp > ans)	ans = tmp;
		System.out.println(ans);
	}
}

class InputReader
{
	public InputReader() {
		// TODO Auto-generated constructor stub
		tokenizer = new StringTokenizer("");
		reader = new BufferedReader(new InputStreamReader(System.in));
	}
	public String nextTokenizer()	throws IOException
	{
		while (!tokenizer.hasMoreTokens())
		{
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
		
	}
	public int nextInt()	throws IOException
	{
		return Integer.valueOf(nextTokenizer());
	}

	StringTokenizer tokenizer;
	BufferedReader	reader;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值