【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();
	}
};
相关推荐
陌小呆^O^5 分钟前
Cmakelist.txt之win-c-udp-server
c语言·开发语言·udp
C++忠实粉丝5 分钟前
计算机网络socket编程(3)_UDP网络编程实现简单聊天室
linux·网络·c++·网络协议·计算机网络·udp
Gu Gu Study12 分钟前
枚举与lambda表达式,枚举实现单例模式为什么是安全的,lambda表达式与函数式接口的小九九~
java·开发语言
დ旧言~26 分钟前
【高阶数据结构】图论
算法·深度优先·广度优先·宽度优先·推荐算法
时光の尘26 分钟前
C语言菜鸟入门·关键字·float以及double的用法
运维·服务器·c语言·开发语言·stm32·单片机·c
我们的五年31 分钟前
【Linux课程学习】:进程描述---PCB(Process Control Block)
linux·运维·c++
张彦峰ZYF31 分钟前
投资策略规划最优决策分析
分布式·算法·金融
以后不吃煲仔饭40 分钟前
Java基础夯实——2.7 线程上下文切换
java·开发语言
进阶的架构师41 分钟前
2024年Java面试题及答案整理(1000+面试题附答案解析)
java·开发语言
前端拾光者1 小时前
利用D3.js实现数据可视化的简单示例
开发语言·javascript·信息可视化