【Codeforces】CF 1997 E

Level Up

#数据结构 #二分 #树状数组

题目描述

Monocarp is playing a computer game. He starts the game being level 1 1 1. He is about to fight n n n monsters, in order from 1 1 1 to n n n. The level of the i i i-th monster is a i a_i ai.

For each monster in the given order, Monocarp's encounter goes as follows:

  • if Monocarp's level is strictly higher than the monster's level, the monster flees (runs away);
  • otherwise, Monocarp fights the monster.

After every k k k-th fight with a monster (fleeing monsters do not count ), Monocarp's level increases by 1 1 1. So, his level becomes 2 2 2 after k k k monsters he fights, 3 3 3 after 2 k 2k 2k monsters, 4 4 4 after 3 k 3k 3k monsters, and so on.

You need to process q q q queries of the following form:

  • i x i~x i x: will Monocarp fight the i i i-th monster (or will this monster flee) if the parameter k k k is equal to x x x?

输入格式

The first line contains two integers n n n and q q q ( 1 ≤ n , q ≤ 2 ⋅ 1 0 5 1 \le n, q \le 2 \cdot 10^5 1≤n,q≤2⋅105) --- the number of monsters and the number of queries. The second line contains n n n integers a 1 , a 2 , ... , a n a_1, a_2, \dots, a_n a1,a2,...,an ( 1 ≤ a i ≤ 2 ⋅ 1 0 5 1 \le a_i \le 2 \cdot 10^5 1≤ai≤2⋅105) --- the levels of the monsters. In the j j j-th of the following q q q lines, two integers i i i and x x x ( 1 ≤ i , x ≤ n 1 \le i, x \le n 1≤i,x≤n) --- the index of the monster and the number of fights required for a level up in the j j j-th query.

输出格式

For each query, output "YES", if Monocarp will fight the i i i-th monster in this query, and "NO", if the i i i-th monster flees.

样例 #1

样例输入 #1

4 16
2 1 2 1
1 1
2 1
3 1
4 1
1 2
2 2
3 2
4 2
1 3
2 3
3 3
4 3
1 4
2 4
3 4
4 4

样例输出 #1

YES
NO
YES
NO
YES
YES
YES
NO
YES
YES
YES
NO
YES
YES
YES
YES

解法

解题思路

首先我们发现,对于位置 i i i的怪物,能够与它战斗的 k k k一定满足单调性,也就是 k k k越大,就越有可能与它发生战斗,相应的,我们可以得到一个阈值,在这个值之前一定不会战斗,在这个值之后,一定会战斗,我们考虑如何求这个阈值。

因为位置在 i i i怪物之前的怪物可能会发生战斗,从而提升我们的等级,因此,我们需要考虑什么样的怪物对我们的等级会有贡献。

容易发现,如果我们当前可以与怪兽发生战斗的最低等级为 k k k,那么就会对 k − I N F k-INF k−INF的升级轮数具有贡献经验的作用。

因此我们可以从左到右枚举每个怪物 ,然后二分出我们可以与它战斗的最低等级。二分时,我们只需要判断当前的经验能让我们升多少级,并与怪物的等级作比较,最后我们再使用树状数组将 k − I N F k-INF k−INF的升级轮数加上 1 1 1即可。

在预处理之后,就可以进行 O ( 1 ) O(1) O(1)查询啦

代码

cpp 复制代码
const int N = 2e5 + 10;
 
int tree[N];
 
int n, q;
inline int lowbit(int x) { return x & (-x); }
inline void add(int i, int val) {
	while (i <= n) {
		tree[i] += val;
		i += lowbit(i);
	}
}
 
inline int query(int i) {
	int res = 0;
	while (i > 0) {
		res += tree[i];
		i -= lowbit(i);
	}
	return res;
}
 
void solve() {
	std::cin >> n >> q;
 
	std::vector<int>a(n + 1);
	for (int i = 1; i <= n; ++i) {
		std::cin >> a[i];
	}
 
	std::vector<int>res(n + 1);
	for (int i = 1; i <= n; ++i) {
		int l = 1, r = n, k = 1;
		while (l <= r) {
			int mid = l + r >> 1;
			int s = query(mid) / mid + 1;
			if (s <= a[i]) {
				k = mid;
				r = mid - 1;
			}
			else {
				l = mid + 1;
			}
		}
		res[i] = k;
		add(k, 1);
	}
 
	while (q--) {
		int i, x;
		std::cin >> i >> x;
 
		if (x >= res[i]) std::cout << "YES\n";
		else std::cout << "NO\n";
	}
}
 
signed main() {
	std::ios::sync_with_stdio(0);
	std::cin.tie(0);
	std::cout.tie(0);
 
	int t = 1;
	//std::cin >> t;
 
	while (t--) {
		solve();
	}
};
相关推荐
2401_857439692 小时前
SSM 架构下 Vue 电脑测评系统:为电脑性能评估赋能
开发语言·php
SoraLuna2 小时前
「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台
开发语言·macos·ui·华为·harmonyos
xlsw_2 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
Dream_Snowar3 小时前
速通Python 第三节
开发语言·python
唐诺3 小时前
几种广泛使用的 C++ 编译器
c++·编译器
XH华4 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_4 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
高山我梦口香糖4 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
落魄君子4 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘