势能分析 线段树 学习记录

发布于:2025-09-13 ⋅ 阅读:(19) ⋅ 点赞:(0)

算法讲解111【扩展】线段树专题2-线段树的离散化、二分搜索、特别修改_哔哩哔哩_bilibili

对于gcd, 取log, 开根号, 取模, 等操作, 一个数的下降比较快, 可以考虑暴力操作势能分析

P4145 上帝造题的七分钟 2 / 花神游历各国 - 洛谷

对于每个数, 最多操作六次开根号操作就会降到1, 线段树修改操作 直接修改到叶子节点, 但是如果当前区间的最大值是1, 则这个区间不再需要进行操作, 不进入这个区间, 这样的话, 每个数最多操作6次, 加上树高, 一共是6 * logn * n次

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;

//线段树,区间修改,区间查询
//https://www.luogu.com.cn/problem/P3372
template<typename Info, typename Tag>
struct SegmentTree {
#define ls (id<<1)
#define rs (id<<1|1)
	SegmentTree() = default;
	SegmentTree(int n) : n(n), info(n << 2), tag(n << 2), len(n << 2) {}
	SegmentTree(const SegmentTree<Info, Tag> &o) : n(o.n), info(o.info), tag(o.tag) {}
	template<typename T>
	SegmentTree(const std::vector<T> &init) : SegmentTree((int)init.size()) {
		auto build = [&](auto self, int id, int l, int r) ->void {
			len[id] = r - l + 1;
			if(l == r) {
				info[id] = init[l];
				return;
			}
			int mid = (l + r) / 2;
			self(self, ls, l, mid);
			self(self, rs, mid + 1, r);
			pushup(id);
		};
		build(build, 1, 0, n - 1);
	}
	void apply(int id, const Tag &dx) {
		info[id].apply(dx, len[id]);
		tag[id].apply(dx);
	}
	void pushup(int id) {
		info[id] = info[ls] + info[rs];
	}
	void pushdown(int id) {
		apply(ls, tag[id]);
		apply(rs, tag[id]);
		tag[id] = Tag();
	}
	
	void modify(int id, int l, int r, int pos, const Info &val) {
		if(l == r) {
			info[id] = val;
			return;
		}
		pushdown(id);
		int mid = (l + r) / 2;
		if(pos <= mid) {
			modify(ls, l, mid, pos, val);
		} else {
			modify(rs, mid + 1, r, pos, val);
		}
		pushup(id);
	}
	
	void rangeUpdate(int id, int l, int r, int x, int y, const Tag &dx) {
		if (info[id].maxx == 1) {
			return;
		}
		if(l == r) {
			info[id].sum = sqrt(info[id].sum);
			info[id].maxx = sqrt(info[id].maxx);
			return;
		}
		int mid = (l + r) / 2;
		pushdown(id);
		if(x <= mid) {
			rangeUpdate(ls, l, mid, x, y, dx);
		}
		if(y > mid) {
			rangeUpdate(rs, mid + 1, r, x, y, dx);
		}
		pushup(id);
	}
	Info rangeQuery(int id, int l, int r, int x, int y) {
		if(x <= l && r <= y) {
			return info[id];
		}
		int mid = (l + r) / 2;
		pushdown(id);
		Info res;
		if(x <= mid) {
			res = res + rangeQuery(ls, l, mid, x, y);
		}
		if(y > mid) {
			res = res + rangeQuery(rs, mid + 1, r, x, y);
		}
		return res;
	}


	void rangeUpdate(int l, int r, const Tag &dx) {
		rangeUpdate(1, 0, n - 1, l, r, dx);
	}
	void update(int pos, const Tag &dx) {
		rangeUpdate(pos, pos, dx);
	}
	Info rangeQuery(int l, int r) {
		return rangeQuery(1, 0, n - 1, l, r);
	}
	Info query(int pos) {
		return rangeQuery(pos, pos);
	}

	void modify(int pos, const Info &val) {
		return modify(1, 0, n - 1, pos, val);
	}
#undef ls
#undef rs
	int n;
	std::vector<Info> info;
	std::vector<Tag> tag;
	std::vector<int> len;
};

constexpr i64 INF = 4E18;
i64 mod = 1e9 + 7;
struct Tag {
	i64 add = 0;
	i64 mul = 1;
	void apply(const Tag &dx) {
		// mul = (mul * dx.mul) % mod;
		// add = (add * dx.mul + dx.add) % mod;
	}
};

struct Info {
	i64 sum = 0;
	i64 maxx = 0;
	Info() {}
	Info(i64 x) : sum(x), maxx(x) {};
	void apply(const Tag &dx, const int &len) {
		// sum = (sum * dx.mul + dx.add * len) % mod;

	}
};

Info operator+(const Info &x, const Info &y) {
	Info res;
	res.sum = (x.sum + y.sum);
	res.maxx = max(x.maxx, y.maxx);
	return res;
}
void solve() {
	int n;
	cin >> n;
	vector<i64> a(n + 1);
	for (int i = 1; i <= n; i++) cin >> a[i];
	SegmentTree<Info, Tag> seg(a);
	
	int m;
	cin >> m;
	while(m--) {
		int k, l, r;
		cin >> k >> l >> r;
		if (r < l) swap(l, r);

		if (k == 0) {
			Tag tag;
			seg.rangeUpdate(l, r, tag);
		} else {
			cout << seg.rangeQuery(l, r).sum << '\n';
		}
	}





}


int main() {
	std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

	int T = 1;
	//cin >> T;
	while (T--) solve();

	return 0;
}

Problem - D - Codeforces

每次取模操作, 如果mod小于x, 则x取模之后最少减半, 所以一个数最多进行log次取模操作

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
//线段树,区间修改,区间查询
//https://www.luogu.com.cn/problem/P3372
template<typename Info, typename Tag>
struct SegmentTree {
#define ls (id<<1)
#define rs (id<<1|1)
	SegmentTree() = default;
	SegmentTree(int n) : n(n), info(n << 2), tag(n << 2), len(n << 2) {}
	SegmentTree(const SegmentTree<Info, Tag> &o) : n(o.n), info(o.info), tag(o.tag) {}
	template<typename T>
	SegmentTree(const std::vector<T> &init) : SegmentTree((int)init.size()) {
		auto build = [&](auto self, int id, int l, int r) ->void {
			len[id] = r - l + 1;
			if(l == r) {
				info[id] = init[l];
				return;
			}
			int mid = (l + r) / 2;
			self(self, ls, l, mid);
			self(self, rs, mid + 1, r);
			pushup(id);
		};
		build(build, 1, 0, n - 1);
	}
	void apply(int id, const Tag &dx) {
		info[id].apply(dx, len[id]);
		tag[id].apply(dx);
	}
	void pushup(int id) {
		info[id] = info[ls] + info[rs];
	}
	void pushdown(int id) {
		apply(ls, tag[id]);
		apply(rs, tag[id]);
		tag[id] = Tag();
	}
	
	void modify(int id, int l, int r, int pos, const Info &val) {
		if(l == r) {
			info[id] = val;
			return;
		}
		pushdown(id);
		int mid = (l + r) / 2;
		if(pos <= mid) {
			modify(ls, l, mid, pos, val);
		} else {
			modify(rs, mid + 1, r, pos, val);
		}
		pushup(id);
	}
	
	void rangeUpdate(int id, int l, int r, int x, int y, const Tag &dx) {
		if (info[id].maxx < dx.mod) {
			return;
		}
		if (l == r) {
			info[id].maxx %= dx.mod;
			info[id].sum %= dx.mod;
			return;
		}
		
		int mid = (l + r) / 2;
		pushdown(id);
		if(x <= mid) {
			rangeUpdate(ls, l, mid, x, y, dx);
		}
		if(y > mid) {
			rangeUpdate(rs, mid + 1, r, x, y, dx);
		}
		pushup(id);
	}
	Info rangeQuery(int id, int l, int r, int x, int y) {
		if(x <= l && r <= y) {
			return info[id];
		}
		int mid = (l + r) / 2;
		pushdown(id);
		Info res;
		if(x <= mid) {
			res = res + rangeQuery(ls, l, mid, x, y);
		}
		if(y > mid) {
			res = res + rangeQuery(rs, mid + 1, r, x, y);
		}
		return res;
	}


	void rangeUpdate(int l, int r, const Tag &dx) {
		rangeUpdate(1, 0, n - 1, l, r, dx);
	}
	void update(int pos, const Tag &dx) {
		rangeUpdate(pos, pos, dx);
	}
	Info rangeQuery(int l, int r) {
		return rangeQuery(1, 0, n - 1, l, r);
	}
	Info query(int pos) {
		return rangeQuery(pos, pos);
	}

	void modify(int pos, const Info &val) {
		return modify(1, 0, n - 1, pos, val);
	}
#undef ls
#undef rs
	int n;
	std::vector<Info> info;
	std::vector<Tag> tag;
	std::vector<int> len;
};

constexpr i64 INF = 4E18;
i64 mod = 1e9 + 7;
struct Tag {
	i64 mod = 0;
	void apply(const Tag &dx) {
		// mul = (mul * dx.mul) % mod;
		// add = (add * dx.mul + dx.add) % mod;
	}
};

struct Info {
	i64 sum = 0;
	i64 maxx = 0;
	Info() {}
	Info(i64 x) : sum(x), maxx(x) {};
	void apply(const Tag &dx, const int &len) {
		// sum = (sum * dx.mul + dx.add * len) % mod;
	}
};

Info operator+(const Info &x, const Info &y) {
	Info res;
	res.sum = (x.sum + y.sum);
	res.maxx = max(x.maxx, y.maxx);
	return res;
}

void solve() {
	int n, m;
	cin >> n >> m;
	vector<int> a(n + 1);
	for (int i = 1; i <= n; i++) cin >> a[i];
	SegmentTree<Info, Tag> seg(a);
	while(m--) {
		int k;
		cin >> k;
		if (k == 1) {
			int l, r;
			cin >> l >> r;
			cout << seg.rangeQuery(l, r).sum << '\n';
		} else if (k == 2) {
			int l, r, mod;
			cin >> l >> r >> mod;
			Tag tag;
			tag.mod = mod;
			seg.rangeUpdate(l, r, tag);
		} else {
			int i, x;
			cin >> i >> x;
			Info info;
			info = x;
			seg.modify(i, info);
		}
	}






}


int main() {
	std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

	int T = 1;
	//cin >> T;
	while (T--) solve();

	return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到