模板集合(持续更新中)

发布时间 2023-04-23 08:29:31作者: yi_fan0305

线段树

// 线段树
namespace Seg_tree {
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
	
	typedef long long ll;
	const int N = 1e5 + 5;
	using std::max;
	using std::min;
	
	ll val[N << 2], laz[N << 2], maxx[N << 2], minn[N << 2];
	
	template<class T>
	const T& _max(const T& a, const T& b) { // 比较函数
		return a > b ? a : b;
	}
	
	template<class T>
	const T& _min(const T& a, const T& b) { // 比较函数
		return a > b ? b : a;
	}
	
	void pushup(int u) { // 更新信息
		val[u] = val[ls] + val[rs];
		maxx[u] = max(maxx[ls], maxx[rs]);
		minn[u] = min(minn[ls], minn[rs]);
	}
	
	void pushdown(int u, int l, int r) { // 下传标记
		if (!laz[u])	return ;
		laz[ls] += laz[u];
		val[ls] += laz[u] * (mid - l + 1);
		maxx[ls] += laz[u] * (mid - l + 1);
		minn[ls] += laz[u] * (mid - l + 1);
		laz[rs] += laz[u];
		val[rs] += laz[u] * (r - mid);
		maxx[rs] += laz[u] * (r - mid);
		minn[rs] += laz[u] * (r - mid);
		laz[u] = 0;
	}
	
	void build(int u, int l, int r) { // 建树
		laz[u] = 0;
		if (l == r) {
			scanf("%lld", &val[u]);
			maxx[u] = minn[u] = val[u];
			return ;
		}
		build(ls, l, mid);
		build(rs, mid + 1, r);
		pushup(u);
	}
	
	void add(int u, int l, int r, int lr, int rr, ll c) { // 区间加减
		if (lr <= l && r <= rr) {
			laz[u] += c;
			ll tmp = (r - l + 1) * c;
			val[u] += tmp;
			minn[u] += tmp;
			maxx[u] += tmp;
			return ;
		}
		pushdown(u, l, r);
		if (lr <= mid)	add(ls, l, mid, lr, rr, c);
		if (rr > mid)	add(rs, mid + 1, r, lr, rr, c);
		pushup(u);
	}
	
	ll qry(int u, int l, int r, int lr, int rr, ll* g) { // 区间查询,g 为查询的数组名
		if (lr <= l && r <= rr) {
			return g[u];
		}
		pushdown(u, l, r);
		ll ans = 0;
		if (lr <= mid) {
			ans += qry(ls, l, mid, lr, rr, g);
		}
		if (rr > mid) {
			ans += qry(rs, mid + 1, r, lr, rr, g);
		}
		return ans;
	}
}

ST 表

namespace ST_RMQ {
#define MAX 1
#define MIN 0
	
	typedef long long ll;
	const int N = 1e5 + 5;
	using std::max;
	using std::min;
	
	int lg[N];
	ll maxx[N][20], minn[N][20];
	
	template<class T>
	const T& _max(const T& a, const T& b) {
		return a > b ? a : b;
	}
	
	template<class T>
	const T& _min(const T& a, const T& b) {
		return a > b ? b : a;
	}
	
	void pre(int n) { // 预处理 lg
		for (int i = 2; i <= n; ++ i) {
			lg[i] = lg[i >> 1] + 1;
		}
	}
	
	void work(int n) {
		for (int j = 1; j <= lg[n]; ++ j) {
			for (int i = 1; i + (1 << j) - 1 <= n; ++ i) {
				maxx[i][j] = max(maxx[i][j - 1], maxx[i + (1 << j - 1)][j - 1]);
				minn[i][j] = min(minn[i][j - 1], minn[i + (1 << j - 1)][j - 1]);
			}
		}
	}
	
	ll qry(int l, int r, int fg) { // 求最值,fg 为 1 时求最大值,fg 为 2 时求最小值
		int k = lg[r - l + 1];
		if (fg == MAX)	return max(maxx[l][k], maxx[r - (1 << k) + 1][k]);
		if (fg == MIN)	return min(minn[l][k], minn[r - (1 << k) + 1][k]);
		return -1;
	}
}

// 堆
namespace Heap {
	typedef long long ll;
	using std::priority_queue;
	using std::vector;
	using std::queue;
	using std::greater;
	using std::swap;
	const int N = 1e5 + 5;
	
	// 对顶堆
	struct top_heap {
		priority_queue<ll> q1;
		priority_queue<ll, vector<ll>, greater<ll> > q2;
		
		void insert(ll x) { // 插入
			if (q1.empty()) {
				q1.push(x);
				return ;
			}
			if(x > q1.top())	q2.push(x);
			else	q1.push(x);
		}
		
		int K_th(int k) { // 求第 K 大的值
			if (q1.size() + q2.size() < k)	return -1;
			while (q1.size() < k) {
				q1.push(q2.top());
				q2.pop();
			}
			while (q1.size() > k) {
				q2.push(q1.top());
				q1.pop();
			}
			return q1.top();
		}
		
		int pop_K_th(int k) { // 删除第 K 大的值
			if (q1.size() + q2.size() < k)	return -1;
			while (q1.size() < k) {
				q1.push(q2.top());
				q2.pop();
			}
			while (q1.size() > k) {
				q2.push(q1.top());
				q1.pop();
			}
			int u = q1.top();
			q1.pop();
			return u;
		}
	};

	// 可删除堆
	struct del_heap {
		priority_queue<ll, vector<ll>, greater<ll> > q1, q2;
		
		void insert(ll x) { // 插入
			q1.push(x);
		}
		
		void del(ll x) { // 删除
			q2.push(x);
		}
		
		ll top() { // 取堆顶
			while(!q2.empty() && !q1.empty() && q2.top() == q1.top()) {
				q1.pop(), q2.pop();
			}
			return q1.top();
		}
	};

	// 左偏树(小根堆)
	struct leftist_tree {
		int lson[N], rson[N], fa[N], fat[N];
		ll val[N], dist[N];
		
		int merge(int x, int y) { // 合并
			if (!x || !y) {
				return x | y;
			}
			if (val[x] > val[y] || (val[x] == val[y] && x > y))
				swap(x, y);
			rson[x] = merge(rson[x], y);
			fat[rson[x]] = fa[rson[x]] = x;
			if (dist[lson[x]] < dist[rson[x]])
				swap(lson[x], rson[x]);
			dist[x] = dist[rson[x]] + 1;
			return x;
		}
		
		int find(int u) { // 查询堆顶的元素的标号
			return (fat[u] == u || fat[u] == 0) ? u : fat[u] = find(fat[u]);
		}
		
		void earse(int u) { // 删除任意一点
			int tmp = merge(lson[u], rson[u]), fu = fa[u];
			fat[tmp] = fa[tmp] = fu;
			fat[u] = fa[u] = tmp;
			lson[fu] == u ? lson[fu] = tmp : rson[fu] = tmp;
			while (fu) {
				if (dist[lson[fu]] < dist[rson[fu]])
					swap(lson[fu], rson[fu]);
				if (dist[fu] == dist[rson[fu]] + 1)
					return ;
				dist[fu] = dist[rson[fu]] + 1;
				fu = fa[fu];
			}
		}
		
		ll top(int u) { // 查询 u 点所在堆的堆顶元素
			int g = find(u);
			return val[g];
		}
		
		void pop(int u) { // 弹出 u 点所在对的堆顶元素
			int g = find(u);
			earse(g);
		}
		
		int build(int n) { // 建树
			queue<int> q;
			for (int i = 1; i <= n; ++ i) {
				q.push(i);
			}
			int x, y, z;
			while (q.size() > 1) {
				x = q.front(), q.pop();
				y = q.front(), q.pop();
				z = merge(x, y), q.push(z);
			}
			return q.front();
		}
	};
}