Educational Codeforces Round 168 (Rated for Div. 2) E.Level Up

E.Level UP

二分答案 + 树状数组

单调性:因为 k 越小,怪兽越是容易逃跑

对每个怪物,二分答案出与之战斗的最小 k(阙值)

树状数组用于记录在当前位置之前,在不同的 k 下有多少个怪物可以战斗

从前往后遍历,每个位置的阙值为下标,这样pt.get(x)就能得到在参数 kx 时,前面能与多少怪物战斗

  • 因为 k 越大,怪物越容易与其战斗,所以在参数为 x 的情况下,树状数组前面那些阙值小的敌人自然也会战斗
  • 每个位置的敌人都会执行pt.add(x, 1),记录有一个敌人的阙值为 x
#define int long long//记得开long long
//树状数组模板
template<class T> struct BIT {
	int n;
	vector<T> w;
	BIT(int n) : n(n), w(n + 1) {}
	BIT(int n, vector<T> &in) : n(n), w(n + 1) {
		for(int i = 1; i <= n; i++) {
			add(i, in[i]);
		}
	}
	void add(int x, T v) {
		for(; x <= n; x += (x & -x)) {
			w[x] += v;
		}
	}
	T get(int x) {
		T ans = 0;
		for(; x; x -= (x & -x)) {
			ans += w[x];
		}
		return ans;
	}
	T get(int l, int r) {
		return get(r) - get(l - 1);
	}
};

void solve(int cas) {
	int n, q; cin >> n >> q;
	vector<int> a(n + 1), req(n + 1);
	BIT<int> pt(n);
	for(int i = 1; i <= n; i++) cin >> a[i];
	//检查在k为x时,idx处的怪物是否战斗,如果战斗则返回true,逃跑返回false
	auto check = [&](int idx, int x) {
		//pt.get(x)表示在参数k为x的情况下,前面发生战斗的怪物数量
        //a[idx] * x表示要升级到a[idx] + 1级需要战斗a[idx] * x只怪
        //如果实际能战斗的怪物数pt.get(x)比 a[idx] * x少,那战斗完等级就低于或等于怪物等级,此时会战斗,否则等级高于怪物等级,怪物会逃跑
		return a[idx] * x > pt.get(x);
	};
	
	for(int i = 1; i <= n; i++) {
		//二分找出与使怪物战斗的最小k值
		int l = 1, r = n;
		while(l < r) {
			int mid = l + r >> 1;
			if(check(i, mid)) r = mid;
			else l = mid + 1;
		}
		//将树状数组中的l处+1
		pt.add(l, 1);
        //req记录:能与第i的怪物战斗的最小k值为l
		req[i] = l;
	}
	while(q--) {
		int idx, k; cin >> idx >> k;
        //如果比阙值还小,说明等级大于怪物等级,怪物会逃跑
		if(k < req[idx]) cout << "NO" << endl;
		else cout << "YES" << endl;
	}
}
posted @   夕闻  阅读(58)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 基于DeepSeek R1 满血版大模型的个人知识库,回答都源自对你专属文件的深度学习。
· 在缓慢中沉淀,在挑战中重生!2024个人总结!
· 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!
点击右上角即可分享
微信分享提示