LOJ#4148. 「JOISC 2024 Day1」鱼 3

称投喂饲料 A 的逆操作,即「选定一条鱼,使其智力值减少 \(D\)」为操作 \(A_R\)

注意到仅通过投喂饲料 B 得到的序列一定是不降的,问题转化为求通过多少次操作 \(A_R\) 能使得序列不降。

若存在 \(C_{i+1} - C_i < D\),则若 \(C_{i + 1}\) 减小,\(C_i\) 也一定随之减小,可以把它们俩看成一块,称为一个 连续段

离线询问,扫描右端点,线段树维护 \(-D\) 的系数,并查集维护连续段左右端点并支持合并。

每修改 \(k\) 个连续段,就会有 \(k - 1\) 个连续段合并成一个,势能分析法,时间复杂度 \(\mathcal O(n \log n)\),常数大。

代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

constexpr int N = 3e5 + 10;

int n, q;
ll D, c[N], ans[N];

vector<pii> qry[N];

namespace DSU {
	int fa[N], l[N], r[N];
	inline void init(int n) {iota(fa + 1, fa + n + 1, 1), iota(l + 1, l + n + 1, 1), iota(r + 1, r + n + 1, 1);}
	inline int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
	inline int getl(int x) {return l[find(x)];}
	inline void merge(int x, int y) {
		x = find(x), y = find(y);
		if (x != y) fa[y] = x, l[x] = min(l[x], l[y]), r[x] = max(r[x], r[y]);
	}
}

namespace SGT {
	#define lson pos << 1
	#define rson pos << 1 | 1

	ll w[N << 2], lazy[N << 2];

	inline void fix(int pos, int l, int r, ll c) {w[pos] += (r - l + 1) * c, lazy[pos] += c;}

	inline void pu(int pos) {w[pos] = w[lson] + w[rson];}

	inline void pd(int pos, int l, int r) {
		if (!lazy[pos]) return;
		int mid = (l + r) >> 1;
		fix(lson, l, mid, lazy[pos]), fix(rson, mid + 1, r, lazy[pos]);
		lazy[pos] = 0;
	}

	void upd(int pos, int l, int r, int x, int y, ll c) {
		if (x <= l && r <= y) return fix(pos, l, r, c);
		pd(pos, l, r); int mid = (l + r) >> 1;
		if (x <= mid) upd(lson, l, mid, x, y, c);
		if (y > mid) upd(rson, mid + 1, r, x, y, c);
		pu(pos);
	}

	ll qry(int pos, int l, int r, int x, int y) {
		if (x <= l && r <= y) return w[pos];
		pd(pos, l, r); int mid = (l + r) >> 1;
		if (y <= mid) return qry(lson, l, mid, x, y);
		if (x > mid) return qry(rson, mid + 1, r, x, y);
		return qry(lson, l, mid, x, y) + qry(rson, mid + 1, r, x, y);
	}
}

inline ll getc(int i) {return c[i] - D * SGT::qry(1, 1, n, i, i);}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
	cin >> n >> D;
	for (int i = 1; i <= n; i++) cin >> c[i];
	cin >> q;
	for (int i = 1, l, r; i <= q; i++) cin >> l >> r, qry[r].emplace_back(l, i);
	DSU::init(n);
	for (int i = 2; i <= n; i++) {
		if (c[i - 1] > c[i]) {
			for (int r = i - 1, l; r; r = l - 1) {
				l = DSU::getl(r);
				ll cl = getc(r), cr = getc(r + 1);
				if (cl <= cr) break;
				SGT::upd(1, 1, n, l, r, (cl - cr + D - 1) / D);
				DSU::merge(r, r + 1);
			}
		}
		for (auto qi : qry[i]) {
			if (getc(qi.first) < 0) ans[qi.second] = -1;
			else ans[qi.second] = SGT::qry(1, 1, n, qi.first, i);
		}
	}
	for (int i = 1; i <= q; i++) cout << ans[i] << '\n';
	return 0;
}

作者:chy12321

出处:https://www.cnblogs.com/chy12321/p/18211097

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Chy12321  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up dark_mode palette
选择主题