数据结构

数据结构

莫队

int n, m;
/*====================*/
int S;
struct Query
{
	int l, r, idx;
	Query(int _l = 0, int _r = 0, int _idx = 0)
	{
		l = _l, r = _r, idx = _idx;
	}
	friend bool operator<(const Query& a, const Query& b)
	{
		return (a.l / S == b.l / S) ? (((a.l / S) & 1) ? (a.r > b.r) : (a.r < b.r)) : (a.l < b.l);
	}
}query[M];
/*====================*/
int ans[M];
/*====================*/
void Add(int pos)
{

}
void Del(int pos)
{

}
/*====================*/
void Mo(void)
{
	cin >> n >> m;
	S = n / sqrt(m) + 1;
	for (int i = 1; i <= m; ++i)
	{
		int l, r; cin >> l >> r;
		query[i] = Query(l, r, i);
	}
	sort(query + 1, query + 1 + m);
	int l = 1, r = 0;
	for (int i = 1; i <= m; ++i)
	{
		while (query[i].l < l)Add(--l);
		while (r < query[i].r)Add(++r);
		while (l < query[i].l)Del(l++);
		while (query[i].r < r)Del(r--);
		//获得ans[query[i].idx];
	}
}

猫树

#include<iostream>
using namespace std;

const int N = 1 << 20;
const int LEVEL = 20;

int a[N];
int lg[N];
int pos[N];
int MaoA[LEVEL][N];//最大子段和
int MaoB[LEVEL][N];//最大连续和

inline int ls(int p) { return p << 1; }
inline int rs(int p) { return (p << 1) | 1; }

void Build(int p, int l, int r, int level)
{
	if (l == r) { pos[l] = p; return; }
	int mid = (l + r) >> 1;
	int tempA, tempB;
	//the left
	MaoA[level][mid] = MaoB[level][mid] = a[mid];
	tempA = max(a[mid], 0), tempB = a[mid];
	for (int i = mid - 1; i >= l; --i)
	{
		tempA += a[i]; MaoA[level][i] = max(MaoA[level][i + 1], tempA); tempA = max(tempA, 0);
		tempB += a[i]; MaoB[level][i] = max(MaoB[level][i + 1], tempB);
	}
	//the right
	MaoA[level][mid + 1] = MaoB[level][mid + 1] = a[mid + 1];
	tempA = max(a[mid + 1], 0), tempB = a[mid + 1];
	for (int i = mid + 2; i <= r; ++i)
	{
		tempA += a[i]; MaoA[level][i] = max(MaoA[level][i - 1], tempA); tempA = max(tempA, 0);
		tempB += a[i]; MaoB[level][i] = max(MaoB[level][i - 1], tempB);
	}
	//
	Build(ls(p), l, mid, level + 1); Build(rs(p), mid + 1, r, level + 1);
}
int Ask(int l, int r)
{
	if (l == r)return a[l];
	int level = (lg[pos[l]] - lg[pos[l] ^ pos[r]]);
	return max(max(MaoA[level][l], MaoA[level][r]), MaoB[level][l] + MaoB[level][r]);
}

int main()
{
	int n; cin >> n;
	int len = 1; while (len < n)len <<= 1;
	for (int i = 2; i < N; ++i)lg[i] = lg[i >> 1] + 1;
	for (int i = 1; i <= n; ++i)cin >> a[i];
	Build(1, 1, len, 1);
	int m; cin >> m;
	for (int i = 1; i <= m; ++i)
	{
		int l, r; cin >> l >> r;
		cout << Ask(l, r) << endl;
	}
	return 0;
}

ST表

通用ST表

template<class Type>
class C_ST
{
private:
	Type(*op)(Type, Type);
	vector<vector<Type>>table;
public:
	void Init(int n, Type arr[], Type(*op)(Type, Type))
	{
		this->op = op;
		/*====================*/
		table.assign(__lg(n) + 1, vector<Type>(n + 1, Type()));
		for (int i = 1; i <= n; ++i)table[0][i] = arr[i];
		/*====================*/
		for (int d = 1; (1 << d) <= n; ++d)
		{
			for (int i = 1; i + (1 << d) - 1 <= n; ++i)
			{
				table[d][i] = op(table[d - 1][i], table[d - 1][i + (1 << (d - 1))]);
			}
		}
	}
	Type operator()(int l, int r)
	{
		int d = __lg(r - l + 1); return op(table[d][l], table[d][r - (1 << d) + 1]);
	}
};

线性RMQ

template<class Type, class Comp = less<Type>>
class C_RMQ
{
private:
	using ull = unsigned long long;
	/*====================*/
	struct Block
	{
		int l, r;
		ull stk[64];
		Type pre[64];
		Type suf[64];
		Block(void) { l = r = 0; }
	};
	/*====================*/
	vector<Type>arr;
	Comp cmp = Comp();
	vector<int>belong;
	vector<Block>block;
	vector<vector<Type>>table;
	/*====================*/
	Type Valu(const Type& a, const Type& b)
	{
		return cmp(a, b) ? a : b;
	}
	Type BlockValu(int l, int r)
	{
		int d = __lg(r - l + 1); return Valu(table[d][l], table[d][r - (1 << d) + 1]);
	}
public:
	void Init(int n, Type arr[])
	{
		this->arr.assign(n + 1, Type());
		for (int i = 1; i <= n; ++i)this->arr[i] = arr[i];
		/*====================*/
		int b = (n + 63) / 64;
		/*====================*/
		belong.assign(n + 1, 0);
		block.assign(b + 1, Block());
		for (int i = 1; i <= n; ++i)
		{
			belong[i] = (i - 1) / 64 + 1;
			if (block[belong[i]].l == 0)
			{
				block[belong[i]].l = i;
			}
			block[belong[i]].r = i;
		}
		for (int i = 1; i <= n; ++i)
		{
			int idx = (i - 1) & 63;
			if (i == block[belong[i]].l)
			{
				block[belong[i]].pre[idx] = arr[i];
			}
			else
			{
				block[belong[i]].pre[idx] = Valu(block[belong[i]].pre[idx - 1], arr[i]);
			}
		}
		for (int i = n; i >= 1; --i)
		{
			int idx = (i - 1) & 63;
			if (i == block[belong[i]].r)
			{
				block[belong[i]].suf[idx] = arr[i];
			}
			else
			{
				block[belong[i]].suf[idx] = Valu(block[belong[i]].suf[idx + 1], arr[i]);
			}
		}
		for (int i = 1; i <= b; ++i)
		{
			ull stk = 0;
			for (int j = block[i].l; j <= block[i].r; ++j)
			{
				int idx = (j - 1) & 63;
				while (stk && cmp(arr[j], arr[(((i - 1) << 6) | __lg(stk)) + 1]))
				{
					stk ^= (1ull << __lg(stk));
				}
				block[i].stk[idx] = (stk ^= (1ull << idx));
			}
		}
		/*====================*/
		table.assign(__lg(b) + 1, vector<Type>(b + 1, Type()));
		for (int i = 1; i <= b; ++i)table[0][i] = block[i].suf[0];
		for (int d = 1; (1 << d) <= b; ++d)
		{
			for (int i = 1; i + (1 << d) - 1 <= b; ++i)
			{
				table[d][i] = Valu(table[d - 1][i], table[d - 1][i + (1 << (d - 1))]);
			}
		}
	}
	Type operator()(int l, int r)
	{
		int idxl = (l - 1) & 63, idxr = (r - 1) & 63;
		if (belong[l] == belong[r])return arr[(((belong[r] - 1) << 6) | (__builtin_ctzll(block[belong[r]].stk[idxr] >> idxl) + idxl)) + 1];
		if (belong[l] + 1 == belong[r])return Valu(block[belong[l]].suf[idxl], block[belong[r]].pre[idxr]);
		return Valu(Valu(block[belong[l]].suf[idxl], block[belong[r]].pre[idxr]), BlockValu(belong[l] + 1, belong[r] - 1));
	}
};

扫描线

矩形面积并

namespace ScanLine
{
	const int N = 1e5 + 10;
	/*====================*/
	struct Rectangle
	{
		double x1, y1;
		double x2, y2;
	};
	Rectangle rectangle[N];
	/*====================*/
	vector<double>pos;
	/*====================*/
	struct Line
	{
		int val;
		int l, r; 
		double h;
		Line(int _l = 0, int _r = 0, double _h = 0, int _val = 0)
		{
			l = _l, r = _r, h = _h, val = _val;
		}
		friend bool operator<(const Line& a, const Line& b)
		{
			if (a.h != b.h)
			{
				return a.h < b.h;
			}
			else
			{
				return  a.val > b.val;
			}
		}
	};
	vector<Line>line;
	/*====================*/
	struct Tree
	{
		int l, r;
		int cnt; double len;
	};
	Tree tree[N << 3];
	int ls(int p)
	{
		return p << 1;
	}
	int rs(int p)
	{
		return p << 1 | 1;
	}
	void PushUp(int p)
	{
		if (tree[p].cnt >= 1)
		{
			tree[p].len = pos[tree[p].r] - pos[tree[p].l - 1];
		}
		else
		{
			if (tree[p].l != tree[p].r)
			{
				tree[p].len = tree[ls(p)].len + tree[rs(p)].len;
			}
			else
			{
				tree[p].len = 0;
			}
		}
	}
	void Build(int p, int l, int r)
	{
		tree[p].l = l, tree[p].r = r;
		tree[p].cnt = 0; tree[p].len = 0;
		if (tree[p].l != tree[p].r)
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			Build(ls(p), l, mid + 0);
			Build(rs(p), mid + 1, r);
		}
	}
	void Change(int p, int l, int r, int d)
	{
		if (l <= tree[p].l && tree[p].r <= r)
		{
			tree[p].cnt += d; PushUp(p);
		}
		else
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			if (l <= mid)Change(ls(p), l, r, d);
			if (mid < r) Change(rs(p), l, r, d);
			PushUp(p);
		}
	}
	/*====================*/
	double Init(void)
	{
		int n; cin >> n;
		pos.clear(); line.clear();
		for (int i = 1; i <= n; ++i)
		{
			double x1, y1; cin >> x1 >> y1;//左上
			double x2, y2; cin >> x2 >> y2;//右下
			pos.push_back(x1); pos.push_back(x2);
			rectangle[i].x1 = x1; rectangle[i].y1 = y1;
			rectangle[i].x2 = x2; rectangle[i].y2 = y2;
		}
		sort(pos.begin(), pos.end());
		pos.erase(unique(pos.begin(), pos.end()), pos.end());
		for (int i = 1; i <= n; ++i)
		{
			int l = lower_bound(pos.begin(), pos.end(), rectangle[i].x1) - pos.begin();
			int r = lower_bound(pos.begin(), pos.end(), rectangle[i].x2) - pos.begin();
			line.push_back(Line(l, r, rectangle[i].y1, +1));
			line.push_back(Line(l, r, rectangle[i].y2, -1));
		}
		sort(line.begin(), line.end());
		Build(1, 1, pos.size() - 1);
		bool flag = true;
		double ans = 0.0;
		double last = 0.0;
		auto it = line.begin();
		while (it != line.end())
		{
			double high = it->h;
			if (flag)last = high, flag = false;
			ans += (high - last) * tree[1].len;
			while (it != line.end() && it->h == high)
			{
				Change(1, it->l + 1, it->r, it->val); it++;
			}
			last = high;
		}
		return ans;
	}
}

矩形面积交

namespace ScanLine
{
	const int N = 1e5 + 10;
	/*====================*/
	struct Rectangle
	{
		double x1, y1;
		double x2, y2;
	};
	Rectangle rectangle[N];
	/*====================*/
	vector<double>pos;
	/*====================*/
	struct Line
	{
		int val;
		int l, r; 
		double h;
		Line(int _l = 0, int _r = 0, double _h = 0, int _val = 0)
		{
			l = _l, r = _r, h = _h, val = _val;
		}
		friend bool operator<(const Line& a, const Line& b)
		{
			if (a.h != b.h)
			{
				return a.h < b.h;
			}
			else
			{
				return  a.val > b.val;
			}
		}
	};
	vector<Line>line;
	/*====================*/
	struct Tree
	{
		int cnt;
		int l, r;
		double len1;
		double len2;
	};
	Tree tree[N << 3];
	int ls(int p)
	{
		return p << 1;
	}
	int rs(int p)
	{
		return p << 1 | 1;
	}
	void PushUp(int p)
	{
		if (tree[p].cnt >= 1)
		{
			tree[p].len1 = pos[tree[p].r] - pos[tree[p].l - 1];
		}
		else
		{
			if (tree[p].l != tree[p].r)
			{
				tree[p].len1 = tree[ls(p)].len1 + tree[rs(p)].len1;
			}
			else
			{
				tree[p].len1 = 0;
			}
		}
		if (tree[p].cnt >= 2)
		{
			tree[p].len2 = pos[tree[p].r] - pos[tree[p].l - 1];
		}
		else
		{
			if (tree[p].l != tree[p].r)
			{
				if (tree[p].cnt == 1)
				{
					tree[p].len2 = tree[ls(p)].len1 + tree[rs(p)].len1;
				}
				else
				{
					tree[p].len2 = tree[ls(p)].len2 + tree[rs(p)].len2;
				}
			}
			else
			{
				tree[p].len2 = 0;
			}
		}
	}
	void Build(int p, int l, int r)
	{
		tree[p].cnt = 0;
		tree[p].l = l, tree[p].r = r;
		tree[p].len1 = 0; tree[p].len2 = 0;
		if (tree[p].l != tree[p].r)
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			Build(ls(p), l, mid + 0);
			Build(rs(p), mid + 1, r);
		}
	}
	void Change(int p, int l, int r, int d)
	{
		if (l <= tree[p].l && tree[p].r <= r)
		{
			tree[p].cnt += d; PushUp(p);
		}
		else
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			if (l <= mid)Change(ls(p), l, r, d);
			if (mid < r) Change(rs(p), l, r, d);
			PushUp(p);
		}
	}
	/*====================*/
	double Init(void)
	{
		int n; cin >> n;
		pos.clear(); line.clear();
		for (int i = 1; i <= n; ++i)
		{
			double x1, y1; cin >> x1 >> y1;//左上
			double x2, y2; cin >> x2 >> y2;//右下
			pos.push_back(x1); pos.push_back(x2);
			rectangle[i].x1 = x1; rectangle[i].y1 = y1;
			rectangle[i].x2 = x2; rectangle[i].y2 = y2;
		}
		sort(pos.begin(), pos.end());
		pos.erase(unique(pos.begin(), pos.end()), pos.end());
		for (int i = 1; i <= n; ++i)
		{
			int l = lower_bound(pos.begin(), pos.end(), rectangle[i].x1) - pos.begin();
			int r = lower_bound(pos.begin(), pos.end(), rectangle[i].x2) - pos.begin();
			line.push_back(Line(l, r, rectangle[i].y1, +1));
			line.push_back(Line(l, r, rectangle[i].y2, -1));
		}
		sort(line.begin(), line.end());
		Build(1, 1, pos.size() - 1);
		bool flag = true;
		double ans = 0.0;
		double last = 0.0;
		auto it = line.begin();
		while (it != line.end())
		{
			double high = it->h;
			if (flag)last = high, flag = false;
			ans += (high - last) * tree[1].len2;
			while (it != line.end() && it->h == high)
			{
				Change(1, it->l + 1, it->r, it->val); it++;
			}
			last = high;
		}
		return ans;
	}
}

矩形周长并

namespace ScanLine
{
	const int N = 1e5 + 10;
	/*====================*/
	struct Rectangle
	{
		double x1, y1;
		double x2, y2;
	};
	Rectangle rectangle[N];
	/*====================*/
	vector<double>pos;
	/*====================*/
	struct Line
	{
		int val;
		int l, r;
		double h;
		Line(int _l = 0, int _r = 0, double _h = 0, int _val = 0)
		{
			l = _l, r = _r, h = _h, val = _val;
		}
		friend bool operator<(const Line& a, const Line& b)
		{
			if (a.h != b.h)
			{
				return a.h < b.h;
			}
			else
			{
				return  a.val > b.val;
			}
		}
	};
	vector<Line>line;
	typedef vector<Line>::iterator iter;
	/*====================*/
	struct Tree
	{
		int l, r;
		int cnt; double len;
	};
	Tree tree[N << 3];
	int ls(int p)
	{
		return p << 1;
	}
	int rs(int p)
	{
		return p << 1 | 1;
	}
	void PushUp(int p)
	{
		if (tree[p].cnt >= 1)
		{
			tree[p].len = pos[tree[p].r] - pos[tree[p].l - 1];
		}
		else
		{
			if (tree[p].l != tree[p].r)
			{
				tree[p].len = tree[ls(p)].len + tree[rs(p)].len;
			}
			else
			{
				tree[p].len = 0;
			}
		}
	}
	void Build(int p, int l, int r)
	{
		tree[p].l = l, tree[p].r = r;
		tree[p].cnt = 0; tree[p].len = 0;
		if (tree[p].l != tree[p].r)
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			Build(ls(p), l, mid + 0);
			Build(rs(p), mid + 1, r);
		}
	}
	void Change(int p, int l, int r, int d)
	{
		if (l <= tree[p].l && tree[p].r <= r)
		{
			tree[p].cnt += d; PushUp(p);
		}
		else
		{
			int mid = (tree[p].l + tree[p].r) >> 1;
			if (l <= mid)Change(ls(p), l, r, d);
			if (mid < r) Change(rs(p), l, r, d);
			PushUp(p);
		}
	}
	/*====================*/
	double Init(void)
	{
		int n; cin >> n; double ans = 0;
		for (int i = 1; i <= n; ++i)
		{
			double x1, y1; cin >> x1 >> y1;//左上
			double x2, y2; cin >> x2 >> y2;//右下
			rectangle[i].x1 = x1; rectangle[i].y1 = y1;
			rectangle[i].x2 = x2; rectangle[i].y2 = y2;
		}
		/*====================*/
		pos.clear(); line.clear();
		for (int i = 1; i <= n; ++i)
		{
			pos.push_back(rectangle[i].x1);
			pos.push_back(rectangle[i].x2);
		}
		sort(pos.begin(), pos.end());
		pos.erase(unique(pos.begin(), pos.end()), pos.end());
		for (int i = 1; i <= n; ++i)
		{
			int l = lower_bound(pos.begin(), pos.end(), rectangle[i].x1) - pos.begin();
			int r = lower_bound(pos.begin(), pos.end(), rectangle[i].x2) - pos.begin();
			line.push_back(Line(l, r, rectangle[i].y1, +1));
			line.push_back(Line(l, r, rectangle[i].y2, -1));
		}
		sort(line.begin(), line.end());
		Build(1, 1, pos.size() - 1);
		double last1 = 0;
		for (iter it = line.begin(); it != line.end(); ++it)
		{
			Change(1, it->l + 1, it->r, it->val);
			ans += abs(tree[1].len - last1); last1 = tree[1].len;
		}
		/*====================*/
		pos.clear(); line.clear();
		for (int i = 1; i <= n; ++i)
		{
			pos.push_back(rectangle[i].y1);
			pos.push_back(rectangle[i].y2);
		}
		sort(pos.begin(), pos.end());
		pos.erase(unique(pos.begin(), pos.end()), pos.end());
		for (int i = 1; i <= n; ++i)
		{
			int l = lower_bound(pos.begin(), pos.end(), rectangle[i].y1) - pos.begin();
			int r = lower_bound(pos.begin(), pos.end(), rectangle[i].y2) - pos.begin();
			line.push_back(Line(l, r, rectangle[i].x1, +1));
			line.push_back(Line(l, r, rectangle[i].x2, -1));
		}
		sort(line.begin(), line.end());
		Build(1, 1, pos.size() - 1);
		double last2 = 0;
		for (iter it = line.begin(); it != line.end(); ++it)
		{
			Change(1, it->l + 1, it->r, it->val);
			ans += abs(tree[1].len - last2); last2 = tree[1].len;
		}
		/*====================*/
		return ans;
	}
}

可删堆

template<class Type, class Comp = greater<Type>>
class C_Heap
{
private:
	priority_queue<Type, vector<Type>, Comp>heap1;
	priority_queue<Type, vector<Type>, Comp>heap2;
public:
	Type Top(void)
	{
		while (!heap2.empty() && heap1.top() == heap2.top())
		{
			heap1.pop(); heap2.pop();
		}
		return heap1.top();
	}
	void Pop(void)
	{
		while (!heap2.empty() && heap1.top() == heap2.top())
		{
			heap1.pop(); heap2.pop();
		}
		heap1.pop();
	}
	int Size(void)
	{
		return heap1.size() - heap2.size();
	}
	void Clear(void)
	{
		while (!heap1.empty())heap1.pop();
		while (!heap2.empty())heap2.pop();
	}
	bool Empty(void)
	{
		return heap1.size() == heap2.size();
	}
	void Erase(Type val)
	{
		heap2.push(val);
	}
	void Insert(Type val)
	{
		heap1.push(val);
	}
};

并查集

普通并查集

class C_DSU
{
private:
	vector<int>pre, siz;
	/*====================*/
	int Find(int cur)
	{
		return cur == pre[cur] ? cur : pre[cur] = Find(pre[cur]);
	}
public:
	void Init(int n)
	{
		pre.assign(n + 1, 0);siz.assign(n + 1, 1);
		for (int i = 0; i <= n; ++i)pre[i] = i;
	}
	int operator[](int cur)
	{
		return Find(cur);
	}
	void operator()(int u, int v)
	{
		u = Find(u), v = Find(v);
		if (siz[u] < siz[v])
		{
			pre[u] = v, siz[v] += siz[u];
		}
		else
		{
			pre[v] = u, siz[u] += siz[v];
		}
	}
};

可撤销并查集

class C_DSU
{
private:
	vector<int>pre, siz;
	vector<pair<int, int>>record;
	/*====================*/
	int Find(int cur)
	{
		return cur == pre[cur] ? cur : Find(pre[cur]);
	}
public:
	void Init(int n)
	{
		pre.assign(n + 1, 0); siz.assign(n + 1, 1);
		for (int i = 0; i <= n; ++i)pre[i] = i;
	}
	int operator[](int cur)
	{
		return Find(cur);
	}
	void operator()(int u, int v)
	{
		u = Find(u), v = Find(v);
		if (siz[u] < siz[v])
		{
			pre[u] = v, siz[v] += siz[u];
			record.push_back({ u,v });
			
		}
		else
		{
			pre[v] = u, siz[u] += siz[v];
			record.push_back({ v,u });
		}
	}
	void Cancel(void)
	{
		int u = record.back().first;
		int v = record.back().second;
		siz[v] -= siz[u]; pre[u] = u;
		record.pop_back();
	}
};

平衡树

带旋·Treap·权值树

template<class Valu>
class C_Treap
{
private:
	struct Tree
	{
		int siz;
		Valu valu;
		int priority;
		Tree* lch, * rch;
		Tree(void)
		{
			siz = 0;
			valu = Valu();
			lch = rch = NULL;
			priority = rand();
		}
	};
	/*====================*/
	Tree* null, * root;
	/*====================*/
	Tree* Creat(Valu valu)
	{
		Tree* node = new Tree;
		node->valu = valu;
		node->lch = null;
		node->rch = null;
		node->siz = 1;
		return node;
	}
	/*====================*/
	void PushUp(Tree* cur)
	{
		cur->siz = cur->lch->siz + cur->rch->siz + 1;
	}
	/*====================*/
	void LRotate(Tree*& cur)
	{
		Tree* son = cur->rch;
		cur->rch = son->lch; son->lch = cur; cur = son;
		PushUp(cur->lch); PushUp(cur);
	}
	void RRotate(Tree*& cur)
	{
		Tree* son = cur->lch;
		cur->lch = son->rch; son->rch = cur; cur = son;
		PushUp(cur->rch); PushUp(cur);
	}
	/*====================*/
	void Insert(Tree*& cur, Valu valu)
	{
		if (cur == null)
		{
			cur = Creat(valu);
		}
		else
		{
			if (valu < cur->valu)
			{
				Insert(cur->lch, valu);
				if (cur->priority < cur->lch->priority)
				{
					RRotate(cur);
				}
			}
			else
			{
				Insert(cur->rch, valu);
				if (cur->priority < cur->rch->priority)
				{
					LRotate(cur);
				}
			}
			PushUp(cur);
		}
	}
	void Delete(Tree*& cur, Valu valu)
	{
		if (cur == null)return;
		if (valu == cur->valu)
		{
			if (cur->lch != null && cur->rch != null)
			{
				if (cur->lch->priority < cur->rch->priority)
				{
					LRotate(cur); Delete(cur->lch, valu); PushUp(cur);
				}
				else
				{
					RRotate(cur); Delete(cur->rch, valu); PushUp(cur);
				}
			}
			else if (cur->lch != null)
			{
				RRotate(cur); Delete(cur->rch, valu); PushUp(cur);
			}
			else if (cur->rch != null)
			{
				LRotate(cur); Delete(cur->lch, valu); PushUp(cur);
			}
			else
			{
				delete cur; cur = null;
			}
		}
		else
		{
			if (valu < cur->valu)
			{
				Delete(cur->lch, valu);
			}
			else
			{
				Delete(cur->rch, valu);
			}
			PushUp(cur);
		}
	}
	/*====================*/
	Valu GetValuByRank(int rank)
	{
		Tree* cur = root;
		while (cur != null)
		{
			if (cur->lch->siz + 1 == rank)
			{
				return cur->valu;
			}
			else
			{
				if (cur->lch->siz < rank)
				{
					rank -= cur->lch->siz + 1;
					cur = cur->rch;
				}
				else
				{
					cur = cur->lch;
				}
			}
		}
		return Valu();
	}
	int GetRankByValu(Valu valu)
	{
		int res = 1;
		Tree* cur = root;
		while (cur != null)
		{
			if (cur->valu < valu)
			{
				res += cur->lch->siz + 1;
				cur = cur->rch;
			}
			else
			{
				cur = cur->lch;
			}
		}
		return res;
	}
	/*====================*/
	void Clear(Tree* cur)
	{
		if (cur != null)
		{
			Clear(cur->lch);
			Clear(cur->rch);
			delete cur;
		}
	}
public:
	C_Treap(void)
	{
		root = null = new Tree;
	}
	~C_Treap(void)
	{
		Clear(root); delete null;
	}
	/*====================*/
	int Size(void)
	{
		return root->siz;
	}
	void Clear(void)
	{
		Clear(root); root = null;
	}
	bool Empty(void)
	{
		return root->siz == 0;
	}
	void Erase(Valu valu)
	{
		Delete(root, valu);
	}
	void Insert(Valu valu)
	{
		Insert(root, valu);
	}
	int operator()(Valu valu)
	{
		return GetRankByValu(valu);
	}
	Valu operator[](int rank)
	{
		return GetValuByRank(rank);
	}
};

无旋·Treap·序列树

template<class Valu>
class C_Treap
{
public:
	struct Tree
	{
		int siz = 0;
		Valu valu = Valu();
		int priority = rand();
		Tree* lch = NULL, * rch = NULL;
	};
	/*====================*/
	Tree* null, * root;
	/*====================*/
	Tree* Creat(Valu valu)
	{
		Tree* node = new Tree;
		node->valu = valu;
		node->lch = null;
		node->rch = null;
		node->siz = 1;
		return node;
	}
	/*====================*/
	void PushUp(Tree* cur)
	{
		cur->siz = cur->lch->siz + cur->rch->siz + 1;
	}
	void PushDown(Tree* cur)
	{
		/*
		* 预留
		*/
	}
	/*====================*/
	Tree* Build(int l, int r, Valu arr[])
	{
		if (l > r)return null;
		int mid = (l + r) >> 1;
		Tree* cur = Creat(arr[mid]);
		cur->lch = Build(l, mid - 1, arr);
		cur->rch = Build(mid + 1, r, arr);
		PushUp(cur); return cur;
	}
	Tree* Build(int l, int r, vector<Valu>& arr)
	{
		if (l > r)return null;
		int mid = (l + r) >> 1;
		Tree* cur = Creat(arr[mid]);
		cur->lch = Build(l, mid - 1, arr);
		cur->rch = Build(mid + 1, r, arr);
		PushUp(cur); return cur;
	}
	/*====================*/
	void Lower_Split(Tree* cur, int index, Tree*& ltree, Tree*& rtree)//index留在rtree
	{
		if (cur == null)
		{
			ltree = rtree = null; return;
		}
		PushDown(cur);
		if (cur->lch->siz + 1 < index)
		{
			Lower_Split(cur->rch, index - cur->lch->siz - 1, ltree, rtree);
			cur->rch = ltree; PushUp(cur); ltree = cur;
		}
		else
		{
			Lower_Split(cur->lch, index, ltree, rtree);
			cur->lch = rtree; PushUp(cur); rtree = cur;
		}
	}
	void Upper_Split(Tree* cur, int index, Tree*& ltree, Tree*& rtree)//index留在ltree
	{
		if (cur == null)
		{
			ltree = rtree = null; return;
		}
		PushDown(cur);
		if (cur->lch->siz < index)
		{
			Upper_Split(cur->rch, index - cur->lch->siz - 1, ltree, rtree);
			cur->rch = ltree; PushUp(cur); ltree = cur;
		}
		else
		{
			Upper_Split(cur->lch, index, ltree, rtree);
			cur->lch = rtree; PushUp(cur); rtree = cur;
		}
	}
	/*====================*/
	Tree* Merge(Tree* ltree, Tree* rtree)
	{
		if (ltree == null)return rtree;
		if (rtree == null)return ltree;
		PushDown(ltree); PushDown(rtree);
		if (ltree->priority < rtree->priority)
		{
			rtree->lch = Merge(ltree, rtree->lch);
			PushUp(rtree); return rtree;
		}
		else
		{
			ltree->rch = Merge(ltree->rch, rtree);
			PushUp(ltree); return ltree;
		}
	}
	/*====================*/
	void Split(int l, int r, Tree*& ltree, Tree*& mtree, Tree*& rtree)
	{
		Tree* o1, * o2, * o3, * o4;
		Upper_Split(root, r, o1, o2);
		Lower_Split(o1, l, o3, o4);
		ltree = o3, mtree = o4, rtree = o2;
	}
	void Merge(Tree* ltree, Tree* mtree, Tree* rtree)
	{
		root = Merge(Merge(ltree, mtree), rtree);
	}
	/*====================*/
	Valu operator[](int rank)
	{
		Tree* cur = root;
		while (cur != null)
		{
			PushDown(cur);
			if (cur->lch->siz + 1 == rank)
			{
				return cur->valu;
			}
			else
			{
				if (cur->lch->siz < rank)
				{
					rank -= cur->lch->siz + 1;
					cur = cur->rch;
				}
				else
				{
					cur = cur->lch;
				}
			}
		}
		return Valu();
	}
	/*====================*/
	C_Treap(void)
	{
		root = null = new Tree;
	}
	void Clear(Tree* cur)
	{
		if (cur != null)
		{
			Clear(cur->lch);
			Clear(cur->rch);
			delete cur;
		}
	}
	~C_Treap(void)
	{
		Clear(root); delete null;
	}
};

双旋·Splay·权值树

template<class Type>
class Splay
{
public:
	~Splay(void)
	{
		Clear(root);
		delete null;
	}
	int size(void)
	{
		return count;
	}
	void clear(void)
	{
		Clear(root);
		root = null;
	}
	bool empty(void)
	{
		return count == 0;
	}
	Type pre(Type val)
	{
		root = splay(FindPre(root, val));
		return root->val;
	}
	Type nxt(Type val)
	{
		root = splay(FindNxt(root, val));
		return root->val;
	}
	void erase(Type val)
	{
		count--; root = Delete(FindByValu(root, val));
	}
	void insert(Type val)
	{
		count++; root = splay(Insert(root, val));
	}
	int operator()(Type val)
	{
		root = splay(FindByValu(root, val));
		return root->lch->siz + 1;
	}
	Type operator[](int rank)
	{
		root = splay(FindByRank(root, rank));
		return root->val;
	}
	Type lower_bound(Type val)
	{
		root = splay(FindLower(root, val));
		return root->val;
	}
	Type upper_bound(Type val)
	{
		root = splay(FindUpper(root, val));
		return root->val;
	}
private:
	struct Node
	{
		int siz = 0;
		Type val = Type();
		Node* fa = NULL;
		Node* lch = NULL;
		Node* rch = NULL;
	};
	/*====================*/
	typedef bool CHILD;
	const CHILD LCH = true;
	const CHILD RCH = false;
	/*====================*/
	int count = 0;
	Node* null = new Node;
	Node* root = null;
	/*====================*/
	CHILD Child(Node* cur)
	{
		Node* pre = cur->fa;
		if (pre->lch == cur)
		{
			return LCH;
		}
		else
		{
			return RCH;
		}
	}

	void PushUp(Node* cur)
	{
		cur->siz = cur->lch->siz + cur->rch->siz + 1;
	}

	void Del(Node* cur, Node* pre, CHILD WCH)
	{
		cur->fa = null;
		if (WCH == LCH)pre->lch = null;
		if (WCH == RCH)pre->rch = null;
	}
	void Add(Node* cur, Node* pre, CHILD WCH)
	{
		cur->fa = pre;
		if (WCH == LCH)pre->lch = cur;
		if (WCH == RCH)pre->rch = cur;
	}

	void LRotate(Node* cur)
	{
		Node* pre = cur->fa, * nxt = cur->lch, * anc = pre->fa;
		CHILD WCH = Child(pre);
		Del(nxt, cur, LCH); Del(cur, pre, RCH); Del(pre, anc, WCH);
		Add(nxt, pre, RCH); Add(pre, cur, LCH); Add(cur, anc, WCH);
		PushUp(pre); PushUp(cur);
	}
	void RRotate(Node* cur)
	{
		Node* pre = cur->fa, * nxt = cur->rch, * anc = pre->fa;
		CHILD WCH = Child(pre);
		Del(nxt, cur, RCH); Del(cur, pre, LCH); Del(pre, anc, WCH);
		Add(nxt, pre, LCH); Add(pre, cur, RCH); Add(cur, anc, WCH);
		PushUp(pre); PushUp(cur);
	}

	void Rotate(Node* cur)
	{
		if (Child(cur) == LCH)
		{
			RRotate(cur);
		}
		else
		{
			LRotate(cur);
		}
	}

	void Clear(Node* cur)
	{
		if (cur != null)
		{
			Clear(cur->lch);
			Clear(cur->rch);
			delete cur;
		}
	}

	Node* Creat(Type val)
	{
		Node* cur = new Node;
		cur->lch = null;
		cur->rch = null;
		cur->fa = null;
		cur->val = val;
		cur->siz = 1;
		return cur;
	}

	Node* splay(Node* cur)
	{
		while (true)
		{
			Node* pre = cur->fa;
			if (cur->fa == null)break;
			if (pre->fa == null)break;
			CHILD CHpre = Child(pre);
			CHILD CHcur = Child(cur);
			if (CHpre == CHcur)
			{
				Rotate(pre); Rotate(cur); continue;
			}
			if (CHpre != CHcur)
			{
				Rotate(cur); Rotate(cur); continue;
			}
		}
		if (cur->fa != null)Rotate(cur); return cur;
	}

	Node* Insert(Node* cur, Type val)
	{
		CHILD WCH = LCH; Node* pre = null;
		while (cur != null)
		{
			if (val < cur->val)
			{
				pre = cur; cur = cur->lch; WCH = LCH;
			}
			else
			{
				pre = cur; cur = cur->rch; WCH = RCH;
			}
		}
		cur = Creat(val); Add(cur, pre, WCH); return cur;
	}

	Node* Delete(Node* cur)
	{
		splay(cur);
		Node* lch = cur->lch;
		Node* rch = cur->rch;
		delete cur; return Merge(lch, rch);
	}

	Node* Merge(Node* ltree, Node* rtree)
	{
		if (ltree == null)
		{
			rtree->fa = null; return rtree;
		}
		if (rtree == null)
		{
			ltree->fa = null; return ltree;
		}
		ltree->fa = null; rtree->fa = null;
		if (ltree->siz < rtree->siz)
		{
			Node* cur = FindMax(ltree); splay(cur);
			Add(rtree, cur, RCH); PushUp(cur); return cur;
		}
		else
		{
			Node* cur = FindMin(rtree); splay(cur);
			Add(ltree, cur, LCH); PushUp(cur); return cur;
		}
	}

	Node* FindByValu(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (val == cur->val)
			{
				res = cur, cur = cur->lch;
			}
			else
			{
				if (val < cur->val)
				{
					cur = cur->lch;
				}
				else
				{
					cur = cur->rch;
				}
			}
		}
		return res;
	}
	Node* FindByRank(Node* cur, int rank)
	{
		while (cur != null)
		{
			if (cur->lch->siz + 1 == rank)
			{
				return cur;
			}
			else
			{
				if (cur->lch->siz < rank)
				{
					rank -= cur->lch->siz + 1;
					cur = cur->rch;
				}
				else
				{
					cur = cur->lch;
				}
			}
		}
		return null;
	}

	Node* FindLower(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (cur->val < val)
			{
				cur = cur->rch;
			}
			else
			{
				res = cur;
				cur = cur->lch;
			}
		}
		return res;
	}
	Node* FindUpper(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (val < cur->val)
			{
				res = cur;
				cur = cur->lch;
			}
			else
			{
				cur = cur->rch;
			}
		}
		return res;
	}

	Node* FindMin(Node* cur)
	{
		while (cur->lch != null)
		{
			cur = cur->lch;
		}
		return cur;
	}
	Node* FindMax(Node* cur)
	{
		while (cur->rch != null)
		{
			cur = cur->rch;
		}
		return cur;
	}

	Node* FindPre(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (cur->val < val)
			{
				res = cur;
				cur = cur->rch;
			}
			else
			{
				cur = cur->lch;
			}
		}
		return res;
	}
	Node* FindNxt(Node* cur, Type val)
	{
		Node* res = null;
		while (cur != null)
		{
			if (val < cur->val)
			{
				res = cur;
				cur = cur->lch;
			}
			else
			{
				cur = cur->rch;
			}
		}
		return res;
	}
};

笛卡尔树

template<class Type>
class C_CartesianTree
{
public:
	struct Tree
	{
		int fa, lch, rch;
		Tree(void)
		{
			fa = lch = rch = -1;
		}
	};
private:
	int root; vector<Tree>tree;
public:
	void Init(int n, Type arr[])
	{
		root = -1; tree.assign(n + 1, Tree());
		vector<int>stk(n + 1, 0); int cnt = 0;
		for (int i = 1; i <= n; ++i)
		{
			int top = cnt; while (top && arr[i] < arr[stk[top]])--top;
			if (top)tree[stk[top]].rch = i, tree[i].fa = stk[top];
			if (top < cnt)tree[i].lch = stk[top + 1], tree[stk[top + 1]].fa = i;
			stk[cnt = ++top] = i;
		}
		root = stk[1];
	}
	int Root(void)
	{
		return root;
	}
	const Tree& operator[](int idx)
	{
		return tree[idx];
	}
};

珂朵莉树

namespace Chtholly
{
	struct Tree
	{
		int l, r;
		mutable int val;
		Tree(int _l = 0, int _r = 0, int _val = int())
		{
			l = _l, r = _r, val = _val;
		}
		friend bool operator<(const Tree& a, const Tree& b)
		{
			return a.l < b.l;
		}
		int len(void)const { return r - l + 1; }
	};
	/*====================*/
	int n; set<Tree>tree;
	/*====================*/
	set<Tree>::iterator Find(int pos)
	{
		return --tree.upper_bound(Tree(pos));
	}
	set<Tree>::iterator Split(int pos)//lower
	{
		if (pos > n)return tree.end();
		auto it = Find(pos); if (it->l == pos)return it;
		int l = it->l, r = it->r; auto val = it->val; tree.erase(it);
		tree.insert(Tree(l, pos - 1, val)); return tree.insert(Tree(pos, r, val)).first;
	}
	/*====================*/
	void GetRange(int l, int r, auto& begin, auto& end)
	{
		end = Split(r + 1), begin = Split(l);
	}
	void EraseRange(int l, int r)
	{
		set<Tree>::iterator begin, end; GetRange(l, r, begin, end); tree.erase(begin, end);
	}
	void InsertRange(int l, int r, int val)
	{
		EraseRange(l, r); auto it = tree.insert(Tree(l, r, val)).first;
		{auto __it = it; __it--; if (it != tree.begin() && __it->val == val)l = __it->l; }
		{auto __it = it; __it++; if (__it != tree.end() && __it->val == val)r = __it->r; }
		EraseRange(l, r); tree.insert(Tree(l, r, val));
	}
	/*====================*/
	void Build(int _n)
	{
		n = _n; tree.insert(Tree(1, n, 1));
	}
}

树状数组

权值树状数组

class C_FenwickTree
{
private:
	int n, m; vector<int>tree;
	/*====================*/
	int lowbit(int x) { return x & (-x); }
public:
	int Size(void)
	{
		return tree[0];
	}
	void Init(int n)
	{
		this->n = n; m = 0;
		tree.assign(n + 1, 0);
		while ((1 << (m + 1)) <= n)m++;
	}
	bool Empty(void)
	{
		return tree[0] == 0;
	}
	void Erase(int x)
	{
		tree[0]--;
		while (x <= n)
		{
			tree[x] -= 1; x += lowbit(x);
		}
	}
	void Insert(int x)
	{
		tree[0]++;
		while (x <= n)
		{
			tree[x] += 1; x += lowbit(x);
		}
	}
	int operator()(int valu)
	{
		valu--;
		int rank = 0;
		while (valu)
		{
			rank += tree[valu];
			valu -= lowbit(valu);
		}
		return rank + 1;
	}
	int operator[](int rank)
	{
		int sum = 0, valu = 0;
		for (int i = m; i >= 0; --i)
		{
			int temp = valu + (1 << i);
			if (temp <= n && sum + tree[temp] < rank)
			{
				sum += tree[temp]; valu = temp;
			}
		}
		return valu + 1;
	}
};

一维树状数组

template<class Type>
class C_FenwickTree
{
private:
	int n; vector<Type>tree;
	/*====================*/
	int lowbit(int x) { return x & (-x); }
public:
	void Init(int n)
	{
		this->n = n; tree.assign(n + 1, Type());
	}
	void Add(int pos, Type d)
	{
		while (pos <= n)
		{
			tree[pos] += d;
			pos += lowbit(pos);
		}
	}
	Type Ask(int pos)
	{
		Type res = Type();
		while (pos)
		{
			res += tree[pos];
			pos -= lowbit(pos);
		}
		return res;
	}
	Type Ask(int l, int r)
	{
		if (l > r)return Type();
		Type res = Type(); l--;
		while (r > l)res += tree[r], r -= lowbit(r);
		while (l > r)res -= tree[l], l -= lowbit(l);
		return res;
	}
};

二维树状数组

template<class Type>
class FenwickTree
{
private:
	int n, m; vector<vector<Type>>tree;
	/*====================*/
	int lowbit(int x) { return x & (-x); }
public:
	void Init(int n, int m)
	{
		this->n = n, this->m = m;
		tree.assign(n + 1, vector<Type>(m + 1, Type()));
	}
	void Add(int x, int y, Type d)
	{
		while (x <= n)
		{
			int tempy = y;
			while (tempy <= m)
			{
				tree[x][tempy] += d;
				tempy += lowbit(tempy);
			}
			x += lowbit(x);
		}
	}
	Type Ask(int x, int y)
	{
		Type res = Type();
		while (x)
		{
			int tempy = y;
			while (tempy)
			{
				res += tree[x][tempy];
				tempy -= lowbit(tempy);
			}
			x -= lowbit(x);
		}
		return res;
	}
	Type Ask(int x_1, int y_1, int x_2, int y_2)
	{
		return Ask(x_2, y_2) - Ask(x_1 - 1, y_2) - Ask(x_2, y_1 - 1) + Ask(x_1 - 1, y_1 - 1);
	}
};

任意维树状数组

using i64 = long long;

template <class T>
class MultiFenwick {
    std::vector<T> t;
    std::vector<int> dimens;
    std::vector<int> scale;

public:
    MultiFenwick(std::vector<int> _scale) : scale(_scale) {
        const int n = scale.size();
        assert(n >= 1);
        dimens.assign(n, 1);
        for (int i = n - 1; i > 0; i--) {
            dimens[i - 1] = dimens[i] * scale[i];
        }

        const int totalScale = dimens[0] * scale[0];
        t.assign(totalScale, T{});
    }

    void modify(const std::vector<int> &inds, const T &x) {
        auto cur = inds;
        auto dfs = [&](auto &&self, int p, int realIndex) -> void {
            if (p >= dimens.size()) {
                t[realIndex] += x;
                return;
            }
            cur[p] = inds[p] + 1;
            while (cur[p] <= scale[p]) {
                self(self, p + 1, realIndex + (cur[p] - 1) * dimens[p]);
                cur[p] += cur[p] & -cur[p];
            }
        };
        dfs(dfs, 0, 0);
    }

    T query(const std::vector<int> &inds) {
        T res = T{};
        auto cur = inds;
        auto dfs = [&](auto &&self, int p, int realIndex) -> void {
            if (p >= dimens.size()) {
                res += t[realIndex];
                return;
            }
            cur[p] = inds[p] + 1;
            while (cur[p] > 0) {
                self(self, p + 1, realIndex + (cur[p] - 1) * dimens[p]);
                cur[p] -= cur[p] & -cur[p];
            }
        };
        dfs(dfs, 0, 0);

        return res;
    }

区间问题

在线静态区间kth

template<class Type>
class C_Range_kth
{
private:
	struct Tree
	{
		int cnt;
		int ls, rs;
		Tree(void)
		{
			cnt = 0; ls = rs = -1;
		}
	};
	/*====================*/
	vector<int>root;
	vector<Tree>tree;
	/*====================*/
	int Creat(void)
	{
		tree.push_back(Tree());
		return tree.size() - 1;
	}
	void Build(int& cur, int treel, int treer)
	{
		cur = Creat();
		if (treel == treer)return;
		int mid = (treel + treer) >> 1;
		Build(tree[cur].ls, treel, mid + 0);
		Build(tree[cur].rs, mid + 1, treer);
	}
	void Insert(int pre, int& cur, int x, int treel, int treer)
	{
		cur = Creat();
		tree[cur] = tree[pre]; tree[cur].cnt++;
		if (treel == treer)return;
		int mid = (treel + treer) >> 1;
		if (x <= mid)Insert(tree[pre].ls, tree[cur].ls, x, treel, mid + 0);
		if (mid < x) Insert(tree[pre].rs, tree[cur].rs, x, mid + 1, treer);
	}
	int Ask(int pre, int cur, int k, int treel, int treer)
	{
		if (treel == treer)return treel;
		int mid = (treel + treer) >> 1;
		int cnt = tree[tree[cur].ls].cnt - tree[tree[pre].ls].cnt;
		if (cnt < k)return Ask(tree[pre].rs, tree[cur].rs, k - cnt, mid + 1, treer);
		else return Ask(tree[pre].ls, tree[cur].ls, k, treel, mid + 0);
	}
	/*====================*/
	vector<Type>lib;
public:
	void Init(int n, Type arr[])
	{
		for (int i = 1; i <= n; ++i)
		{
			lib.push_back(arr[i]);
		}
		sort(lib.begin(), lib.end());
		lib.erase(unique(lib.begin(), lib.end()), lib.end());
		/*====================*/
		tree.reserve(2 * lib.size() + n * (ceil(log2(lib.size())) + 1));
		/*====================*/
		root.assign(n + 1, -1);
		Build(root[0], 1, lib.size());
		for (int i = 1; i <= n; ++i)
		{
			int x = lower_bound(lib.begin(), lib.end(), arr[i]) - lib.begin() + 1;
			Insert(root[i - 1], root[i], x, 1, lib.size());
		}
	}
	Type operator()(int l, int r, int k)
	{
		return lib[Ask(root[l - 1], root[r], k, 1, lib.size()) - 1];
	}
};

在线静态区间mex

class C_Range_mex
{
private:
	struct Tree
	{
		int idx;
		int ls, rs;
		Tree(void)
		{
			idx = 0; ls = rs = -1;
		}
	};
	/*====================*/
	int n;
	vector<int>root;
	vector<Tree>tree;
	/*====================*/
	int Creat(void)
	{
		tree.push_back(Tree());
		return tree.size() - 1;
	}
	void Build(int& cur, int treel, int treer)
	{
		cur = Creat();
		if (treel == treer)return;
		int mid = (treel + treer) >> 1;
		Build(tree[cur].ls, treel, mid + 0);
		Build(tree[cur].rs, mid + 1, treer);
	}
	void Insert(int pre, int& cur, int num, int idx, int treel, int treer)
	{
		cur = Creat();
		tree[cur] = tree[pre];
		if (treel == treer)
		{
			tree[cur].idx = idx;
		}
		else
		{
			int mid = (treel + treer) >> 1;
			if (num <= mid)Insert(tree[pre].ls, tree[cur].ls, num, idx, treel, mid + 0);
			if (mid < num) Insert(tree[pre].rs, tree[cur].rs, num, idx, mid + 1, treer);
			tree[cur].idx = min(tree[tree[cur].ls].idx, tree[tree[cur].rs].idx);
		}
	}
	int Ask(int cur, int idx, int treel, int treer)
	{
		if (treel == treer)return treel;
		int mid = (treel + treer) >> 1;
		if (tree[tree[cur].ls].idx < idx)return Ask(tree[cur].ls, idx, treel, mid + 0);
		if (tree[tree[cur].rs].idx < idx)return Ask(tree[cur].rs, idx, mid + 1, treer);
		return treer + 1;
	}
public:
	void Init(int n, int arr[])
	{
		tree.reserve(2 * n + n * (ceil(log2(n)) + 1));
		/*====================*/
		this->n = n;
		root.assign(n + 1, -1);
		Build(root[0], 0, n - 1);
		for (int i = 1; i <= n; ++i)
		{
			root[i] = root[i - 1];
			if (arr[i] < n)
			{
				Insert(root[i - 1], root[i], arr[i], i, 0, n - 1);
			}
		}
	}
	int operator()(int l, int r)
	{
		return Ask(root[r], l, 0, n - 1);
	}
};

Hash_MAP

const int Base = 19260817;
class Hash_Map 
{
public:
	Hash_Map()
	{
		memset(head, -1, sizeof(head));
		nxt.reserve(1e7);
		key.reserve(1e7);
		val.reserve(1e7);
	}
	lnt& operator[](lnt k)
	{
		int h = hash(k);
		for (int i = head[h]; ~i; i = nxt[i])
		{
			if (key[i] == k)
			{
				return val[i];
			}
		}
		nxt.push_back(head[h]);
		key.push_back(k);
		val.push_back(0);
		head[h] = nxt.size() - 1;
		return val.back();
	}
	lnt has_key(lnt k) 
	{
		int h = hash(k);
		for (int i = head[h]; ~i; i = nxt[i])
		{
			if (key[i] == k)
			{
				return true;
			}
		}
		return false;
	}
private:
	int head[Base];
	vector<int>nxt;
	vector<lnt>key;
	vector<lnt>val;
	int hash(lnt k) 
	{ 
		return k % Base; 
	}
};

线段树合并

/*
* 与动态开点权值线段树搭配使用
*/
Tree* Merge(Tree*& a, Tree*& b, int treel, int treer)
{
	Tree* cur = null;
	if (a == null)
	{
		cur = b; b = null; return cur;
	}
	if (b == null)
	{
		cur = a; a = null; return cur;
	}
	cur = Creat();
	if (treel == treer)
	{
		cur->siz = a->siz + b->siz;
	}
	else
	{
		int mid = (treel + treer) >> 1;
		cur->ls = Merge(a->ls, b->ls, treel, mid + 0);
		cur->rs = Merge(a->rs, b->rs, mid + 1, treer);
		cur->siz = cur->ls->siz + cur->rs->siz;
	}
	delete a; a = null; delete b; b = null; return cur;
}

李超线段树

class C_LiChaoTree
{
private:
	struct Function
	{
		int k, b;
		int operator()(int x)
		{
			return k * x + b;
		}
		Function(int _k = 0, int _b = +INF)
		{
			k = _k, b = _b;
		}
	};
	/*====================*/
	struct Tree
	{
		Function f;
		Tree* ls, * rs;
		Tree(void)
		{
			ls = rs = NULL;
		}
	};
	/*====================*/
	Tree* root; int treel, treer;
	/*====================*/
	void PushDown(Tree*& cur, Function f, int treel, int treer)
	{
		if (cur == NULL)cur = new Tree;
		int mid = (treel + treer) >> 1;
		if (treel != treer)
		{
			if (cur->f.k < f.k)
			{
				if (f(mid) < cur->f(mid))
				{
					PushDown(cur->rs, cur->f, treel, mid + 0);
				}
				else
				{
					PushDown(cur->ls, f, mid + 1, treer);
				}
			}
			else
			{
				if (f(mid) < cur->f(mid))
				{
					PushDown(cur->ls, cur->f, treel, mid + 0);
				}
				else
				{
					PushDown(cur->rs, f, mid + 1, treer);
				}
			}
		}
		if (f(mid) < cur->f(mid))cur->f = f;
	}
	void Add(Tree*& cur, int l, int r, Function f, int treel, int treer)
	{
		if (cur == NULL)cur = new Tree;
		if (l <= treel && treer <= r)
		{
			PushDown(cur, f, treel, treer);
		}
		else
		{
			int mid = (treel + treer) >> 1;
			if (l <= mid)Add(cur->ls, l, r, f, treel, mid + 0);
			if (mid < r) Add(cur->rs, l, r, f, mid + 1, treer);
		}
	}
	int Ask(Tree* cur, int x, int treel, int treer)
	{
		int res = +INF;
		if (cur != NULL)
		{
			res = cur->f(x);
			if (treel != treer)
			{
				int mid = (treel + treer) >> 1;
				if (x <= mid)res = min(res, Ask(cur->ls, x, treel, mid + 0));
				if (mid < x) res = min(res, Ask(cur->rs, x, mid + 1, treer));
			}
		}
		return res;
	}
public:
	C_LiChaoTree(void)
	{
		root = NULL, treel = treer = 0;
	}
	~C_LiChaoTree(void)
	{
		if (root != NULL)
		{
			queue<Tree*>q; q.push(root);
			while (!q.empty())
			{
				if (q.front()->ls != NULL)q.push(q.front()->ls);
				if (q.front()->rs != NULL)q.push(q.front()->rs);
				delete q.front(); q.pop();
			}
		}
	}
    /*====================*/
	void Init(int treel, int treer)
	{
		this->treel = treel;
		this->treer = treer;
	}
	void operator()(int l, int r, Function  f)
	{
		Add(root, l, r, f, treel, treer);
	}
	int operator[](int x)
	{
		return Ask(root, x, treel, treer);
	}
};

可持久化01Trie

int root[N], tot;
int siz[35 * N];
int trie[35 * N][2];
/*====================*/
void Insert(int pre, int cur, lnt num)
{
	for (int i = 32; i >= 0; --i)
	{
		siz[cur] = siz[pre] + 1;
		int bit = (num & (1ll << i)) ? 1 : 0;
		trie[cur][bit ^ 1] = trie[pre][bit ^ 1], trie[cur][bit] = ++tot;
		pre = trie[pre][bit]; cur = trie[cur][bit];
	}
	siz[cur] = siz[pre] + 1;
}
lnt Query(int cur, lnt num, int k)
{
	lnt ans = 0;
	for (int i = 32; i >= 0; --i)
	{
		int bit = (num & (1ll << i)) ? 1 : 0;
		if (siz[trie[cur][bit ^ 1]] >= k)
		{
			ans += 1ll << i;
			cur = trie[cur][bit ^ 1];
		}
		else
		{
			k -= siz[trie[cur][bit ^ 1]];
			cur = trie[cur][bit];
		}
	}
	return ans;
}

Treap维护珂朵莉树

namespace Treap
{
	struct Node
	{
		Range range;
		int priority;
		int lch, rch;
	}node[N * 4];
	/*====================*/
	int null = -1;
	int root = -1;
	/*====================*/
	int Creat(Range range)
	{
		static int cnt = 0; ++cnt;
		node[cnt].lch = null;
		node[cnt].rch = null;
		node[cnt].priority = rand();
		node[cnt].range = range;
		return cnt;
	}
	/*====================*/
	void PushUp(int cur)
	{
		node[cur].range.L = node[cur].range.l;
		node[cur].range.R = node[cur].range.r;
		node[cur].range.Sum = node[cur].range.sum();
		if (node[cur].lch != null)
		{
			node[cur].range.L = node[node[cur].lch].range.L;
			node[cur].range.Sum += node[node[cur].lch].range.Sum;
		}
		if (node[cur].rch != null)
		{
			node[cur].range.R = node[node[cur].rch].range.R;
			node[cur].range.Sum += node[node[cur].rch].range.Sum;
		}
	}
	void PushDown(int cur)
	{
		if (node[cur].range.lazy != 0)
		{
			if (node[cur].lch != null)
			{
				node[node[cur].lch].range.Maintain(node[cur].range.lazy);
			}
			if (node[cur].rch != null)
			{
				node[node[cur].rch].range.Maintain(node[cur].range.lazy);
			}
			node[cur].range.lazy = 0;
		}
	}
	/*====================*/
	int Merge(int ltree, int rtree)
	{
		if (ltree == null)return rtree;
		if (rtree == null)return ltree;
		PushDown(ltree); PushDown(rtree);
		if (node[ltree].priority < node[rtree].priority)
		{
			node[rtree].lch = Merge(ltree, node[rtree].lch);
			/*======*/PushUp(rtree); return rtree;
		}
		else
		{
			node[ltree].rch = Merge(node[ltree].rch, rtree);
			/*======*/PushUp(ltree); return ltree;
		}
	}
	/*====================*/
	void Lower_Split(int cur, unt index, int& ltree, int& rtree)//index留在rtree
	{
		if (cur == null)
		{
			ltree = rtree = null; return;
		}
		PushDown(cur);
		if (node[cur].range.r < index)
		{
			Lower_Split(node[cur].rch, index, ltree, rtree);
			node[cur].rch = ltree; PushUp(cur); ltree = cur;
		}
		else
		{
			Lower_Split(node[cur].lch, index, ltree, rtree);
			node[cur].lch = rtree; PushUp(cur); rtree = cur;
		}
	}
	void Upper_Split(int cur, unt index, int& ltree, int& rtree)//index留在ltree
	{
		if (cur == null)
		{
			ltree = rtree = null; return;
		}
		PushDown(cur);
		if (node[cur].range.l > index)
		{
			Upper_Split(node[cur].lch, index, ltree, rtree);
			node[cur].lch = rtree; PushUp(cur); rtree = cur;
		}
		else
		{

			Upper_Split(node[cur].rch, index, ltree, rtree);
			node[cur].rch = ltree; PushUp(cur); ltree = cur;
		}
	}
	/*====================*/
	void SplitL(int root, unt index, int& ltree, int& rtree)
	{
		int _temp, _ltree, _mtree, _rtree;
		Upper_Split(root, index, _temp, _rtree);
		Lower_Split(_temp, index, _ltree, _mtree);
		unt l = node[_mtree].range.l;
		unt r = node[_mtree].range.r;
		unt val = node[_mtree].range.val;
		if (l != index)
		{
			ltree = Merge(_ltree, Creat(Range(l, index - 1, val)));
			rtree = Merge(Creat(Range(index + 0, r, val)), _rtree);
		}
		else
		{
			ltree = _ltree;
			rtree = Merge(_mtree, _rtree);
		}
	}
	void SplitR(int root, unt index, int& ltree, int& rtree)
	{
		int _temp, _ltree, _mtree, _rtree;
		Upper_Split(root, index, _temp, _rtree);
		Lower_Split(_temp, index, _ltree, _mtree);
		unt l = node[_mtree].range.l;
		unt r = node[_mtree].range.r;
		unt val = node[_mtree].range.val;
		if (r != index)
		{
			ltree = Merge(_ltree, Creat(Range(l, index + 0, val)));
			rtree = Merge(Creat(Range(index + 1, r, val)), _rtree);
		}
		else
		{
			ltree = Merge(_ltree, _mtree);
			rtree = _rtree;
		}
	}
}

动态开点权值线段树

class C_SegmentTree
{
private:
	struct Tree
	{
		int siz;
		Tree* ls, * rs;
		Tree(void)
		{
			siz = 0; ls = rs = NULL;
		}
	};
	/*====================*/
	Tree* null;
	/*====================*/
	Tree* root; int treel, treer;
	/*====================*/
	Tree* Creat(int siz = 0)
	{
		Tree* cur = new Tree;
		cur->siz = siz; cur->ls = cur->rs = null;
		return cur;
	}
	/*====================*/
	void Change(Tree*& cur, int valu, int delta, int treel, int treer)
	{
		if (cur == null)cur = Creat();
		cur->siz += delta;
		if (treel != treer)
		{
			int mid = (treel + treer) >> 1;
			if (valu <= mid)Change(cur->ls, valu, delta, treel, mid + 0);
			if (mid < valu) Change(cur->rs, valu, delta, mid + 1, treer);
		}
	}
    /*====================*/
	int GetValuByRank(Tree* cur, int rank, int treel, int treer)
	{
		if (treel == treer)
		{
			return treel;
		}
		else
		{
			int mid = (treel + treer) >> 1;
			if (cur->ls->siz >= rank)
			{
				return GetValuByRank(cur->ls, rank, treel, mid + 0);
			}
			else
			{
				return GetValuByRank(cur->rs, rank - cur->ls->siz, mid + 1, treer);
			}
		}
	}
	int GetRankByValu(Tree* cur, int valu, int treel, int treer)
	{
		if (cur == null)
		{
			return 0;
		}
		else
		{
			if (treer < valu)
			{
				return cur->siz;
			}
			else
			{
				int res = 0;
				int mid = (treel + treer) >> 1;
				res += GetRankByValu(cur->ls, valu, treel, mid + 0);
				if (mid + 1 < valu) res += GetRankByValu(cur->rs, valu, mid + 1, treer);
				return res;
			}
		}
	}
public:
	C_SegmentTree(void)
	{
		root = null = new Tree; treel = treer = 0;
	}
	~C_SegmentTree(void)
	{
		if (root != null)
		{
			queue<Tree*>q; q.push(root);
			while (!q.empty())
			{
				if (q.front()->ls != null)q.push(q.front()->ls);
				if (q.front()->rs != null)q.push(q.front()->rs);
				delete q.front(); q.pop();
			}
		}
		delete null;
	}
	/*====================*/
	int Size(void)
	{
		return root->siz;
	}
	bool Empty(void)
	{
		return root->siz == 0;
	}
	void Init(int treel, int treer)
	{
		this->treel = treel; this->treer = treer;
	}
	void Erase(int valu)
	{
		Change(root, valu, -1, treel, treer);
	}
	void Insert(int valu)
	{
		Change(root, valu, +1, treel, treer);
	}
	int operator[](int rank)
	{
		return GetValuByRank(root, rank, treel, treer);
	}
	int operator()(int valu)
	{
		return GetRankByValu(root, valu, treel, treer) + 1;
	}
};
posted @ 2025-02-19 22:32  ProtectEMmm  阅读(65)  评论(0)    收藏  举报