bzoj1067: [SCOI2007]降雨量

最水最水最水的一道题目, 完全不需要多说

 

const int N = 50010, D = 17;
struct Node {
	int Year, Water;
	Node() {}
	Node(int _Year, int _Water) : Year(_Year), Water(_Water) {}
} Dat[N];
int Dp[D][N];
int n, m;

inline void Input() {
	scanf("%d", &n);
	For(i, 1, n) scanf("%d%d", &Dat[i].Year, &Dat[i].Water);
	
	// build
	For(i, 1, n) Dp[0][i] = Dat[i].Water;
	For(i, 1, D) {
		if(1 << i > n) break;
		int len = 1 << (i - 1);
		Ford(j, n - len, 1)
			Dp[i][j] = i ? max(Dp[i - 1][j], Dp[i - 1][j + len]) : Dat[j].Water;
	}
}

inline int Find1(int x) {
	int lef = 1, rig = n, mid, ret = n + 1;
	while(lef <= rig) {
		mid = (lef + rig) >> 1;
		if(Dat[mid].Year < x) lef = mid + 1;
		else rig = (ret = mid) - 1;
	}
	return ret;
}
inline int Find2(int x) {
	int lef = 1, rig = n, mid, ret = 0;
	while(lef <= rig) {
		mid = (lef + rig) >> 1;
		if(Dat[mid].Year > x) rig = mid - 1;
		else lef = (ret = mid) + 1;
	}
	return ret;
}
inline int See(int L, int R) {
	if(L > R || L > n) return -INF;
	int len = R - L + 1, Dep;
	for(Dep = 0; 1 << (Dep + 1) <= len; Dep++) ;
	return max(Dp[Dep][L], Dp[Dep][R - (1 << Dep) + 1]);
}
inline void Solve() {
	Dat[0] = Node(-INF, -INF);
	for(scanf("%d", &m); m--; ) {
		int Left, Right, W1, W2;
		scanf("%d%d", &Left, &Right);
		
		W1 = Find1(Left), W2 = Find2(Right);
		if(Dat[W2].Year ^ Right) {
			if(Dat[W1].Year == Left) {
				if(See(W1 + 1, W2) < Dat[W1].Water) printf("maybe\n");
				else printf("false\n");
			} else printf("maybe\n");
		} else if(Dat[W1].Year == Left) {
			if(Dat[W2].Water > Dat[W1].Water || See(W1 + 1, W2 - 1) >= Dat[W2].Water) printf("false\n");
			else if(W2 - W1 == Dat[W2].Year - Dat[W1].Year) printf("true\n");
			else printf("maybe\n");
		} else {
			if(See(W1, W2 - 1) >= Dat[W2].Water) printf("false\n");
			else printf("maybe\n");
		}
	}
}

int main() {
	#ifndef ONLINE_JUDGE
	SETIO("1067");
	#endif
	Input();
	Solve();
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值