小模板

点击查看代码
//模板集合
/*所有private首字母大写 ,所有public接口全小写*/
#pragma GCC optimize("Ofast")
#define LOCAL
#define BIT
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef double db;
typedef long double ldb;
typedef string str;
#define mem(a,b) memset(a, b, sizeof a)
#define debug(x) cerr << #x << '=' << x <<' '
//#define int ll
//#define double ldb
int n, m;
const int N = 5010, M = 20010, MOD = 1e9 + 7;
const int base = 1e8;//进制
const int INF = 1e9;//极大值
template<typename T>T max(T a, T b, T c) {return max(max(a, b), c);}
template<typename T>T min(T a, T b, T c) {return min(min(a, b), c);}
#ifdef BIT//位运算奇技淫巧
	#define lowbit(x)  ((x) & (-(x)))
	#define bin(i) (1 << (i))//生成一个只有第i位为1,其余位为0的数(2^i))
	#define set_bit(x, i) ((x) | bin(i))//将第i位设置为1
	#define clr_bit(x, i) ((x) & (~ bin(i)))//将第i位设置为0
	#define flip_bit(x, i) ((x) ^ bin(i))//切换x的第i位的状态
	#define get_bit(x, i) (((x) >> (i)) & 1)//x的第i位的值
	#define check_adjacent_1(x) ((x) & ((x) >> 1))//检查是否有相邻的1
	int count_bit(int x)
	{
		int sum = 0;
		while(x)
		{
			x &= (x - 1);//清除最低位的1
			++sum;
		}
		return sum;
	}
#endif
namespace IO
{
	#ifndef LOCAL
	const int Z = 1 << 20;
	char buf[Z], *p1 = buf, *p2 = buf, obuf[Z], *p3 = obuf;
	#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, Z, stdin), p1 == p2) ? EOF : *p1++)
	#define flush() (fwrite(obuf, p3-obuf, 1, stdout))
	#define pc(x) ((p3-obuf < Z) ? (*p3++ = x) : (flush(), p3 = obuf , *p3++ = x))
	class Flush {public: ~Flush() {flush();}} _;
	#else
		#define gc() getchar()
		#define pc(x) putchar(x)
	#endif
	char re(char &c) {do c = gc(); while(isspace(c)); return c;}
	void write(const char c) {pc(c);}
	void re(char *c) {char ch; re(ch); do *(c++) = ch; while(!isspace(ch = gc())); *c = '\0';}
	void write(const char *c) {while(*c) pc(*(c++));}
	str re(str &s) {char ch[100]; re(ch), s = ch; return s;}
	void write(const str s) {int len = s.length(); for(int i = 0; i < len; ++i) pc(s[i]);}
	template<typename t1>t1 re(t1 &x) {x = 0; bool f = false; char c = gc(); while(!isdigit(c)) f ^= (c == '-'), c = gc(); while(isdigit(c)) x = (x << 1) + (x << 3) + c - '0', c = gc(); return f ? x = -x : x;}
	template<typename t1>void write(t1 x) {x < 0 ? x = -x, pc('-') : 0; short Stack[65], top = 0; do Stack[++top] = x % 10, x /= 10; while(x > 0); while(top) pc(Stack[top--] + '0');}
	template<typename t1, typename ...t2>void re(t1 &x, t2 &...y) {re(x), re(y...);}
	template<typename t1, typename ...t2>void write(t1 x, t2...y) {write(x), pc(' '), write(y...), pc(' ');}
};
class STL
{
	int a;
	void Vector()
	{
		vector<int> v(N, -1);
		v.begin(), v.end();//返回vector的首、尾迭代器
		v.front(), v.back();//返回vector的首、尾元素
		v.push_back(a);//从vector末尾加入一个元素
		v.size();//返回vector当前的长度(大小)
		v.pop_back();//从vector末尾删除一个元素
		v.empty();//返回vector是否为空,1为空、0不为空
		v.clear();//清空vector
		v.max_size();//输出vector最大容量
		v.capacity();//输出vector真实大小 ,类似size
		v.insert(v.begin() + 1, 1);//插入操作,第一个参数是指针类型,第二个参数是插入对象
		v.erase(v.begin());//删除指定位置的数据
		sort(v.begin(), v.end());
	}
	void Queue()
	{
		queue<int> q;
		q.front(), q.back();//返回queue的首、尾元素
		q.push(a);//从queue末尾加入一个元素
		q.size();//返回queue当前的长度(大小)
		q.pop();//从queue末尾删除一个元素
		q.empty();//返回queue是否为空,1为空、0不为空
	}
	void Stack()
	{
		stack<int> st;
		st.top();//返回stack的栈顶元素
		st.push(a);//从stack栈顶加入一个元素
		st.size();//返回stack当前的长度(大小)
		st.pop();//从stack栈顶弹出一个元素
		st.empty();//返回stack是否为空,1为空、0不为空
	}
	void Priority_queue()
	{
		priority_queue<int> p;
		priority_queue<int, vector<int>, greater<int> > q;
		p.top();//返回priority_queue的首元素
		p.push(a);//向priority_queue中加入一个元素
		p.size();//返回priority_queue当前的长度(大小)
		p.pop();//从priority_queue末尾删除一个元素
		p.empty();//返回priority_queue是否为空,1为空、0不为空
	}
	void Deque()
	{
		deque<int> de;
		de.begin(), de.end();//返回deque的首、尾迭代器
		de.front(), de.back();//返回deque的首、尾元素
		de.push_back(a);//从队尾入队一个元素
		de.push_front(a);//从队头入队一个元素
		de.pop_back();//从队尾出队一个元素
		de.pop_front();//从队头出队一个元素
		de.clear();//清空队列
	}
	void Set()
	{
		set<int> s;
		s.empty();//返回当前集合是否为空,是返回1,否则返回0.
		s.size();//返回当前集合的元素个数。
		s.clear();//清空当前集合。
		s.begin(), s.end();//回集合的首尾迭代器。
		s.insert(a);//表示向集合中加入元素a
		s.erase(a);//表示删除集合中元素a
		s.find(a);//返回集合中指向元素a的迭代器。如果不存在这个元素,就返回s.end(),这个性质可以用来判断集合中有没有这个元素。
		s.lower_bound(a), s.upper_bound(a);//返回集合中第一个大于等于关键字的元素。返回集合中第一个严格大于关键字的元素。
	}
	void Bitset()
	{
		bitset<100> b;
		b.count();//返回b中有多少个1
		b.any(), b.none();//如果,bitset中全都为0,那么any返回0,none()返回1;
		//反之,假如bitset中至少有一个1,那么any返回1,none返回0
		b.set();//把bitset全部置为1
		b.set(a, 1);//把a位置置为1
		b.reset();//把bitset全部置为0
		b.reset(a);//把a位置置为0
		b.flip();//把bitset全部取反
		b.flip(a);//把a位置取反
	}
	void Map()
	{
		map<int, int> mp, mp1;
		mp.insert(pair<int, int>(1, 1));//插入
		mp.find(a);//返回键是a的映射的迭代器
		mp.clear();//清空
		mp.erase(a);//删除一个元素
		mp.erase(mp.begin(), mp.end());
		mp.size();//长度
		mp.begin(), mp.end();//返回指向map头部末尾的迭代器
		mp.empty();//判断其是否为空
		swap(mp, mp1);//交换两个map
	}
};
struct Chain_Forward_Star//链式前向星
{
	struct edge
	{
		int v, w, nxt;//终点,权值,下一条边的编号
	} e[M << 1];
	int head[N], idx;
	Chain_Forward_Star() {clear();}
	void clear()
	{
		idx = 0;
		memset(head, -1, sizeof head);
	}
	void add_edge(int u, int v, int w = 1)//加边
	{
		e[++idx] = {v, w, head[u]};
		head[u] = idx;
	}
};
class Union_Find//并查集
{
  public:
	Union_Find() {clear();}
	void clear(int n_ = N - 1)
	{
		for(int i = 0; i <= n_; ++i)
			fa[i] = i, size[i] = 1;
	}
	int find(int x)//找最大祖先
	{
		return x == fa[x] ? x : fa[x] = find(fa[x]);
	}
	bool merge(int x, int y)//合并,成功返回1,失败返回0
	{
		x = find(x), y = find(y);
		if(x == y) return false;
		if(size[x] < size[y]) swap(x, y);
		fa[y] = x;
		size[x] += size[y];
		size[y] = 0;
		return true;
	}
	bool query(int x, int y)//查询是否在统一集合
	{
		return find(x) == find(y);
	}
	int get_size(int x)//查询所在集合的大小
	{
		return size[find(x)];
	}
  private:
	int fa[N], size[N];
};
struct Dijkstra//最短路
{
	Chain_Forward_Star C;
	int dis[N], dis1[N];//距离
	bool vis[N];//标记
	struct node
	{
		int name, dis;
		bool operator <(const node &x) const
		{
			return x.dis < dis;
		}
	};
	void dijkstra(int s)//最短路
	{
		memset(dis, 0x3f, sizeof dis);//初始化为最大值
		dis[s] = 0;
		priority_queue<node> pq;
		pq.push(node{s, 0});
		while(!pq.empty())
		{
			node tmp = pq.top();
			pq.pop();
			int u = tmp.name;
			if(vis[u]) continue;
			vis[u] = true;
			for(int i = C.head[u]; ~i; i = C.e[i].nxt)
			{
				int v = C.e[i].v, w = C.e[i].w;
				if(dis[u] + w < dis[v])
				{
					dis[v] = dis[u] + w;
					if(!vis[v])
						pq.push(node{v, dis[v]});
				}
			}
		}
	}
	void dijkstra1(int s)//严格次短路
	{
		memset(dis, 0x3f, sizeof dis);
		memset(dis1, 0x3f, sizeof dis1);
		dis[s] = 0;
		priority_queue<node> pq;
		pq.push(node{s, 0});
		while(!pq.empty())
		{
			node tmp = pq.top();
			pq.pop();
			int u = tmp.name;
			for(int i = C.head[u]; ~i; i = C.e[i].nxt)
			{
				int v = C.e[i].v, w = C.e[i].w;
				if(dis[u] + w < dis[v])
				{
					dis1[v] = dis[v];
					dis[v] = dis[u] + w;
					pq.push(node{v, dis[v]});
					pq.push(node{v, dis1[v]});
				}
				else
				{
					if(dis[u] + w < dis1[v] && dis[v] != dis[u] + w)
					{
						dis1[v] = dis[u] + w;
						pq.push(node{v, dis[v]});
						pq.push(node{v, dis1[v]});
					}
					else if(dis1[u] + w < dis1[v] && dis1[u] + w != dis[v])
					{
						dis1[v] = dis1[u] + w;
						pq.push(node{v, dis[v]});
						pq.push(node{v, dis1[v]});
					}
				}
			}
		}
	}
};
class Binary_Index_Tree//树状数组
{
  public:
	Binary_Index_Tree() {clear();}
	void clear() {memset(t, 0, sizeof t);}
	void add(int x, int v)//将x的位置加上v
	{
		while(x <= n)
		{
			t[x] += v;
			x += lowbit(x);
		}
	}
	int sum(int x)//1~x的和
	{
		int res = 0;
		while(x)
		{
			res += t[x];
			x -= lowbit(x);
		}
		return res;
	}
	int query(int l, int r)//查询l~r的区间和
	{
		return sum(r) - sum(l - 1);
	}
  private:
	int t[N];
};
struct Quick//快速算法
{
	ll qpow(ll a, ll b)//快速幂
	{
		ll res = 1;
		a %= MOD;
		while(b)
		{
			if(b & 1) res = (res * a) % MOD;
			a = (a * a) % MOD;
			b >>= 1;
		}
		return res;
	}
	ll qmul(ll a, ll b)//快速乘
	{
		ll res = 0;
		a %= MOD;
		while(b)
		{
			if(b & 1) res = (res + a) % MOD;
			a = (a + a) % MOD;
			b >>= 1;
		}
		return res;
	}
	int exgcd(int a, int b, int &x, int &y)//返回gcd,x,y为ax+by=gcd(a,b)的一组可行解
	{
		if(!b)
		{
			x = 1, y = 0;
			return a;
		}
		int gcd = exgcd(b, a % b, x, y);
		int t = x;
		x = y, y = t - a / b * y;
		return gcd;
	}
	void exgcd1(int a, int b, int &x, int &y)
	{
		if(!b) x = 1, y = 0;
		else
		{
			exgcd1(b, a % b, y, x);
			y -= a / b * x;
		}
	}
};
struct Least_Common_Ancestors//最近公共祖先
{
	Chain_Forward_Star C;
	int depth[N];//深度
	int dis[N];//到根节点的距离
	int Log2[N];
	int fa[N][22];//fa[i][j]为i的(2^j)的父亲
	Least_Common_Ancestors(int n_ = N - 1)
	{
		Log2[0] = Log2[1] = 0;
		for(int i = 2; i <= n_; ++i)
			Log2[i] = Log2[i >> 1] + 1;
	}
	void dfs(int now, int f, int len)//当前,父亲,边的长度
	{
		depth[now] = depth[f] + 1;
		fa[now][0] = f;
		dis[now] = dis[f] + len;
		for(int i = 1; i <= 21; ++i)
			fa[now][i] = fa[fa[now][i - 1]][i - 1];
		for(int i = C.head[now]; ~i; i = C.e[i].nxt)
		{
			int v = C.e[i].v, w = C.e[i].w;
			if(v == f) continue;
			dfs(v, now, w);
		}
	}
	int lca(int x, int y)//最近公共祖先
	{
		if(x == y) return x;
		if(depth[x] < depth[y]) swap(x, y);
		int s = Log2[depth[x] - depth[y]];
		while(s >= 0)
		{
			if(depth[fa[x][s]] >= depth[y])
				x = fa[x][s];
			--s;
		}
		if(x == y) return x;
		s = Log2[depth[x]];
		while(s >= 0)
		{
			if(fa[x][s] != fa[y][s])
			{
				x = fa[x][s];
				y = fa[y][s];
			}
			--s;
		}
		return fa[x][0];
	}
	int query(int x, int y)
	{
		int Lca = lca(x, y);
		return dis[x] + dis[y] - (dis[Lca] << 1);
	}
};
struct Difference_Constraint//差分约束
{
	Chain_Forward_Star C;
	int dis[N];//距离
	int cnt[N];//入队次数
	bool in_queue[N];//是否在队列里
	bool spfa(int s)//返回1则有负环
	{
		memset(dis, 0x3f, sizeof dis);
		dis[s] = 0;
		queue<int> q;
		in_queue[s] = true;
		q.push(s);
		while(!q.empty())
		{
			int u = q.front();
			q.pop();
			in_queue[u] = false;
			for(int i = C.head[u]; ~i; i = C.e[i].nxt)
			{
				int v = C.e[i].v, w = C.e[i].w;
				if(dis[v] > dis[u] + w)
				{
					dis[v] = dis[u] + w;
					if(!in_queue[v])
					{
						++cnt[v];
						if(cnt[v] > n + 1) return true;
						q.push(v);
						in_queue[v] = true;
					}
				}
			}
		}
		return false;
	}
};
struct Kruskal//最小生成树
{
	struct edge
	{
		int u, v, w;
		bool operator <(const edge &x) const
		{
			return w < x.w;
		}
	} e[M];
	Union_Find U;
	int kruskal()
	{
		int tot = 0;//已经选了多少条边
		int res = 0;
		sort(e + 1, e + m + 1);
		for(int i = 1; i <= m; ++i)
			if(U.merge(e[i].u, e[i].v))
			{
				res += e[i].w;
				++tot;
				if(tot == n - 1) break;
			}
		if(tot != n - 1) return -1;
		return res;
	}
};
struct Prim//最小生成树
{
	Chain_Forward_Star C;
	int dis[N];
	bool vis[N];
	struct node
	{
		int name, dis;
		bool operator < (const node &x) const
		{
			return x.dis < dis;
		}
	};
	int prim()
	{
		priority_queue<node> pq;
		int res = 0, tot = 0;//最小生成树边数
		memset(dis, 0x3f, sizeof dis);
		dis[1] = 0;
		pq.push(node{1, 0});
		while(tot < n && !pq.empty())//边数=点数-1
		{
			node tmp = pq.top();
			pq.pop();
			int u = tmp.name;
			if(vis[u]) continue;
			vis[u] = true;
			++tot;
			res += tmp.dis;
			for(int i = C.head[u]; ~i; i = C.e[i].nxt)
			{
				int v = C.e[i].v, w = C.e[i].w;
				if(!vis[v] && dis[v] > w)
				{
					dis[v] = w;
					pq.push(node{v, w});
				}
			}
		}
		if(tot < n) return -1;//不连通
		return res;
	}
};
struct Hungarian_Algorithm//二分图最大匹配匈牙利算法
{
	Chain_Forward_Star C;
	int marry[N];
	bool vis[N];
	bool dfs(int u)
	{
		for(int i = C.head[u]; ~i; i = C.e[i].nxt)
		{
			int v = C.e[i].v;
			if(vis[v]) continue;
			vis[v] = true;
			if(!marry[v] || dfs(marry[v]))
			{
				marry[v] = u;
				return true;
			}
		}
		return false;
	}
	int find_max_matching()
	{
		int matching = 0;
		for(int i = 1; i <= n; ++i)
		{
			memset(vis, false, sizeof vis);
			if(dfs(i)) ++matching;
		}
		return matching;
	}
};
struct Topological_Sorting//拓扑排序
{
	int in[N];
	int res[N], cnt;
	Chain_Forward_Star C;
	Topological_Sorting(): cnt(0) {}
	bool topo()//返回1有环,返回0无环
	{
		queue<int> q;
		for(int i = 1; i <= n; ++i)
			if(in[i] == 0)
			{
				q.push(i);
				res[++cnt] = i;
			}
		while(!q.empty())
		{
			int u = q.front();
			q.pop();
			for(int i = C.head[u]; ~i; i = C.e[i].nxt)
			{
				int v = C.e[i].v;
				--in[v];
				if(in[v] == 0)
				{
					q.push(v);
					res[++cnt] = v;
				}
			}
		}
		if(cnt < n) return true;
		return false;
	}
};
struct Knuth_Morris_Pratt//KMP字符串匹配
{
	int n, m;//n=lena,m=lenb
	int fail[N], f[N];
	int res;//a在b中出现的次数
	char a[N], b[N];
	Knuth_Morris_Pratt(): n(0), m(0), res(0) {}
	void kmp()
	{
		fail[1] = 0;
		for(int i = 2, j = 0; i <= n; ++i)
		{
			while(j > 0 && a[i] != a[j + 1])
				j = fail[j];
			if(a[i] == a[j + 1]) ++j;
			fail[i] = j;
		}
		for(int i = 1, j = 0; i <= m; ++i)
		{
			while(j > 0 && (j == n || b[i] != a[j + 1]))
				j = fail[j];
			if(b[i] == a[j + 1]) ++j;
			f[i] = j;
			if(f[i] == n) ++res;
		}
	}
};
struct Tarjan_Strong_Connectivity_Component//强联通分量
{
	Chain_Forward_Star C;
	int dfn[N], low[N], timestamp;
	stack<int> stk;
	bool in_stk[N];
	int scc[N], scc_cnt, scc_size[N];
	Tarjan_Strong_Connectivity_Component(): timestamp(0), scc_cnt(0) {}
	void tarjan(int u)
	{
		dfn[u] = low[u] = ++timestamp;
		stk.push(u);
		in_stk[u] = true;
		for(int i = C.head[u]; ~i; i = C.e[i].nxt)
		{
			int v = C.e[i].v;
			if(!dfn[v])
			{
				tarjan(v);
				low[u] = min(low[u], low[v]);
			}
			else if(in_stk[v])
				low[u] = min(low[u], low[v]);
		}
		if(dfn[u] == low[u])
		{
			++scc_cnt;
			while(stk.top() != u)
			{
				scc[stk.top()] = scc_cnt;
				++scc_size[scc_cnt];
				in_stk[stk.top()] = false;
				stk.pop();
			}
			scc[stk.top()] = scc_cnt;
			++scc_size[scc_cnt];
			in_stk[stk.top()] = false;
			stk.pop();
		}
	}
};
struct Tarjan_Cutvtex//割点
{
	Chain_Forward_Star C;
	int dfn[N], low[N], timestamp;
	bool cutvertex[N];//是否是割点
	int res;//割点数
	Tarjan_Cutvtex(): timestamp(0), res(0) {}
	void tarjan(int u, int fa)
	{
		dfn[u] = low[u] = ++timestamp;
		int son = 0;
		for(int i = C.head[u]; ~i; i = C.e[i].nxt)
		{
			int v = C.e[i].v;
			if(!dfn[v])
			{
				++son;
				tarjan(v, u);
				low[u] = min(low[u], low[v]);
				if(fa != u && low[v] >= dfn[u] && son && !cutvertex[u])
				{
					cutvertex[u] = true;
					++res;
				}
			}
			else if(v != fa)
				low[u] = min(low[u], dfn[v]);
		}
		if(fa == u && son >= 2 && !cutvertex[u])
		{
			cutvertex[u] = true;
			++res;
		}
	}
};
struct Int//高精度
{
	int num[N];
	Int(int x = 0): num()
	{
		for(int i = x; i; i /= base)
			num[++num[0]] = i % base;
		if(!num[0]) ++num[0];
	}
	void re()
	{
		num[0] = 0;
		char c = getchar();
		while(c < '0' || c > '9')
			c = getchar();
		while(c >= '0' && c <= '9')
			num[++num[0]] = (c - '0'), c = getchar();
		reverse(num + 1, num + num[0] + 1);
//压位
//		char c[N];
//		scanf("%s",c);
//		int lenc = strlen(c);
//		num[0] = 1;
//		for(int r = lenc - 1,l = 0; r >= 0; r = l - 1)
//		{
//			l = r - 8 + 1;
//			if(l < 0)
//				l = 0;
//			for(int i = l; i <= r; ++i)
//				num[num[0]] = (num[num[0]] * 10) + (c[i] - '0');
//			++num[0];
//		}
//		--num[0];
	}
	void write()
	{
		for(int i = num[0]; i >= 1; --i)
			putchar(num[i] + '0');
		putchar('\n');
//压位
//		while (num[0] && !num[num[0]]) --num[0];
//		printf("%lld",num[num[0]]);
//		for(int i = num[0] - 1; i >= 1; --i)
//			printf("%08lld",num[i]);
//		printf("\n");
	}
	Int operator + (const Int &b)
	{
		Int c;
		c.num[0] = max(num[0], b.num[0]);
		for(int i = 1; i <= c.num[0]; ++i)
		{
			c.num[i] += num[i] + b.num[i];
			c.num[i + 1] += c.num[i] / base;
			c.num[i] %= base;
		}
		if(c.num[c.num[0] + 1])
			++c.num[0];
		return c;
	}
	Int operator - (const Int &b)
	{
		Int c;
		c.num[0] = max(num[0], b.num[0]);
		int jiewei = 0;
		for(int i = 1; i <= c.num[0]; ++i)
		{
			c.num[i] = num[i] - b.num[i] - jiewei;
			if(c.num[i] < 0)
				c.num[i] += base, jiewei = 1;
			else jiewei = 0;
		}
		while(c.num[0] > 1 && !c.num[c.num[0]])
			--c.num[0];
		return c;
	}
	Int operator * (const Int &b)
	{
		Int c;
		c.num[0] = num[0] + b.num[0];
		for(int i = 1; i <= num[0]; ++i)
			for(int j = 1; j <= b.num[0]; ++j)
			{
				c.num[i + j - 1] += num[i] * b.num[j];
				c.num[i + j] += c.num[i + j - 1] / base;
				c.num[i + j - 1] %= base;
			}
		while(c.num[0] > 1 && !c.num[c.num[0]])
			--c.num[0];
		return c;
	}
	Int operator / (int k)
	{
		Int c;
		c.num[0] = num[0];
		int x = 0;
		for(int i = num[0]; i >= 1; --i)
		{
			x = x * base + num[i];
			c.num[i] = x / k;
			x %= k;
		}
		while(c.num[0] > 1 && !c.num[c.num[0]])
			--c.num[0];
		return c;
	}
};
bool operator < (const Int &a, const Int &b)
{
	if(a.num[0] != b.num[0])
		return a.num[0] < b.num[0];
	for(int i = a.num[0]; i >= 1; --i)
		if(a.num[i] != b.num[i])
			return a.num[i] < b.num[i];
	return false;
}
bool operator > (const Int &a, const Int &b) {return b < a;}
bool operator <= (const Int &a, const Int &b) {return !(a > b);}
bool operator >= (const Int &a, const Int &b) {return !(a < b);}
Int gcd(Int a, Int b)
{
	if(a < b) swap(a, b);
	int r = 0;//2的次数
	while(b > 0)
	{
		if(a.num[1] % 2 == 0 && b.num[1] % 2 == 0)
			a = a / 2, b = b / 2, ++r;
		else if(a.num[1] % 2 == 0 && b.num[1] % 2 != 0)
			a = a / 2;
		else if(a.num[1] % 2 != 0 && b.num[1] % 2 == 0)
			b = b / 2;
		else a = (a - b) / 2;
		if(a < b) swap(a, b);
	}
	for(int i = 1; i <= r; ++i)
		a = a * 2;
	return a;
}
struct Prime_Sieve//线性筛素数
{
	bool not_prime[N];
	int prime[N];
	void make_prime()
	{
		prime[0] = 0;
		not_prime[1] = true;
		for(int i = 2; i <= n; ++i)
		{
			if(!not_prime[i])
				prime[++prime[0]] = i;
			for(int j = 1; j <= prime[0] && i * prime[j] <= n; ++j)
			{
				not_prime[i * prime[j]] = 1;
				if(i % prime[j] == 0) break;
			}
		}
	}
};
struct Matrix//矩阵
{
	ll a[N][N];
	ll n, m;//行数,列数
	Matrix(int n_ = 0, int m_ = 0): n(n_), m(m_)
	{
		for(int i = 1; i <= n_; ++i)
			for(int j = 1; j <= m_; ++j)
				a[i][j] = 0;
	}
	void re()
	{
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= m; ++j)
				cin >> a[i][j];
	}
	void write()
	{
		for(int i = 1; i <= n; ++i)
		{
			for(int j = 1; j <= m; ++j)
				cout << a[i][j] << ' ';
			cout << '\n';
		}
	}
	Matrix operator + (const Matrix &B)
	{
		Matrix res(n, m);
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= m; ++j)
				res.a[i][j] = a[i][j] + B.a[i][j];
		return res;
	}
	Matrix operator - (const Matrix &B)
	{
		Matrix res(n, m);
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= m; ++j)
				res.a[i][j] = a[i][j] - B.a[i][j];
		return res;
	}
	void operator *=(const ll &k)
	{
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= m; ++j)
				a[i][j] *= k;
	}
	Matrix operator * (const Matrix &B)
	{
		Matrix res(n, B.m);
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= B.m; ++j)
			{
				res.a[i][j] = 0;
				for(int k = 1; k <= m; ++k)
					res.a[i][j] += a[i][k] * B.a[k][j];
			}
		return res;
	}
};
Matrix qpow(Matrix A, ll b)//矩阵快速幂
{
	Matrix res = A, k = A;
	b--;
	while(b)
	{
		if(b & 1) res = res * k;
		k = k * k;
		b >>= 1;
	}
	return res;
}
class Treap_Max//维护了许多信息的Treap
{
	queue<int> trashcan;
	struct Node
	{
		int lson, rson, size, val, cov, key;
		int rev_tag, cov_tag;
		int sum, lmax, rmax, maxn;
	} t[N];
	int root, cnt;
	int new_node(int k)
	{
		int x;
		if(!trashcan.empty())//先垃圾篓里面找
			x = trashcan.front(), trashcan.pop();
		else x = ++cnt;
		t[x].lson = t[x].rson = t[x].cov = t[x].rev_tag = t[x].cov_tag = 0;
		t[x].size = 1;
		t[x].val = t[x].sum = t[x].maxn = k;
		t[x].lmax = t[x].rmax = max(0, k);
		t[x].key = rand();//随机优先级
		return x;
	}
	void push_up(int p)
	{
		if(!p) return;
		t[p].size = t[t[p].lson].size + t[t[p].rson].size + 1;
		t[p].sum = t[t[p].lson].sum + t[t[p].rson].sum + t[p].val;
		t[p].lmax = max(t[t[p].lson].lmax, t[t[p].lson].sum + t[p].val + t[t[p].rson].lmax, 0);//与0取最大
		t[p].rmax = max(t[t[p].rson].rmax, t[t[p].rson].sum + t[p].val + t[t[p].lson].rmax, 0);
		t[p].maxn = max(t[p].val, t[p].val + t[t[p].lson].rmax + t[t[p].rson].lmax);
		if(t[p].lson) t[p].maxn = max(t[p].maxn, t[t[p].lson].maxn);
		if(t[p].rson) t[p].maxn = max(t[p].maxn, t[t[p].rson].maxn);
	}
	void apply_rev(int p)//对以p为根节点的树反转
	{
		if(!p) return ;
		swap(t[p].lson, t[p].rson);
		swap(t[p].lmax, t[p].rmax);
		t[p].rev_tag ^= 1;
	}
	void apply_cov(int p, int c)//对以p为根节点的树覆盖
	{
		t[p].val = t[p].cov = c;
		t[p].sum = t[p].size * c;
		t[p].lmax = t[p].rmax = max(0, t[p].sum);
		t[p].maxn = max(c, t[p].sum);
		t[p].cov_tag = 1;
	}
	void push_down(int p)//下传标记
	{
		if(!p) return;
		if(t[p].rev_tag)//有标记
		{
			if(t[p].lson) apply_rev(t[p].lson);
			if(t[p].rson) apply_rev(t[p].rson);
			t[p].rev_tag = 0;//清空
		}
		if(t[p].cov_tag)//有标记
		{
			if(t[p].lson) apply_cov(t[p].lson, t[p].cov);
			if(t[p].rson) apply_cov(t[p].rson, t[p].cov);
			t[p].cov_tag = t[p].cov = 0;//清空
		}
	}
	void trash(int p)//回收以p为根的子树
	{
		if(!p) return;
		trashcan.push(p);
		if(t[p].lson) trash(t[p].lson);//回收左儿子
		if(t[p].rson) trash(t[p].rson);//回收右儿子
	}
	void split_by_rank(int p, int k, int &x, int &y)//以第k为界限分裂
	{
		if(!p)
		{
			x = y = 0;
			return;
		}
		push_down(p);
		if(t[t[p].lson].size + 1 <= k)//左边装不下
		{
			x = p;
			split_by_rank(t[p].rson, k - t[t[p].lson].size - 1, t[p].rson, y);
		}
		else
		{
			y = p;
			split_by_rank(t[p].lson, k, x, t[p].lson);
		}
		push_up(p);
	}
	int merge(int x, int y)//合并
	{
		if(!x || !y) return x + y;
		if(t[x].key <= t[y].key)
		{
			push_down(x);
			t[x].rson = merge(t[x].rson, y);
			push_up(x);
			return x;
		}
		else
		{
			push_down(y);
			t[y].lson = merge(x, t[y].lson);
			push_up(y);
			return y;
		}
	}
	int a[N];
	int build(int l, int r)//构造a数组的平衡树,避免一个一个插入
	{
		if(l == r) return new_node(a[l]);
		int mid = l + r;
		mid >>= 1;
		return merge(build(l, mid), build(mid + 1, r));
	}
	void insert()//从pos处插入tot个
	{
		int pos, tot;
		cin >> pos >> tot;
		int x, y;
		split_by_rank(root, pos, x, y);
		for(int i = 1; i <= tot; i++)
			cin >> a[i];
		x = merge(x, build(1, tot));
		root = merge(x, y);
	}
	void delet()//从pos处删除tot个
	{
		int pos, tot;
		cin >> pos >> tot;
		int x, y, z;
		split_by_rank(root, pos - 1, x, y);
		split_by_rank(y, tot, y, z);
		trash(y);
		root = merge(x, z);
	}
	void make_same()//从pos处覆盖tot个为c
	{
		int pos, tot, c;
		cin >> pos >> tot >> c;
		int x, y, z;
		split_by_rank(root, pos - 1, x, y);
		split_by_rank(y, tot, y, z);
		apply_cov(y, c);
		root = merge(merge(x, y), z);
	}
	void Reverse()//从pos起翻转tot个
	{
		int pos, tot;
		cin >> pos >> tot;
		int x, y, z;
		split_by_rank(root, pos - 1, x, y);
		split_by_rank(y, tot, y, z);
		apply_rev(y);
		root = merge(merge(x, y), z);
	}
	void get_sum()//a到b区间和
	{
		int a, b;
		cin >> a >> b;
		int x, y, z;
		split_by_rank(root, a - 1, x, y);
		split_by_rank(y, b, y, z);
		cout << t[y].sum << '\n';
		root = merge(merge(x, y), z);
	}
	void max_sum()//最大子段和
	{
		cout << t[root].maxn << '\n';
	}
};
struct Longest_Common_Subsequence//最长公共子序列
{
	int dp[N][N], a[N], b[N];
	int f[N], map[N], ans;
	Longest_Common_Subsequence(): ans(0) {}
	void LCS1()
	{
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= m; ++j)
				if(a[i] == b[j])
					dp[i][j] = dp[i - 1][j - 1] + 1;
				else
					dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
		ans = dp[n][m];
	}
	void LCS2()
	{
		for(int i = 1; i <= n; ++i)
			map[a[i]] = i;
		for(int i = 1; i <= m; ++i)
			f[i] = 0x3f3f3f3f;
		int ans = 0;
		for(int i = 1; i <= m; ++i)
		{
			int l = 0, r = ans, mid;
			if(map[b[i]] > f[ans])
				f[++ans] = map[b[i]];
			else
			{
				while(l < r)
				{
					mid = (l + r) / 2;
					if(f[mid] > map[b[i]])
						r = mid;
					else l = mid + 1;
				}
				f[l] = min(map[b[i]], f[l]);
			}
		}
	}
};
struct Longest_Increasing_Subsequence//最长上升子序列
{
	Longest_Increasing_Subsequence(): ans(0) {}
	int a[N], f[N], ans;
	void LIS()
	{
		for(int i = 1; i <= n; ++i)
		{
			int j = lower_bound(f + 1, f + n + 1, a[i]) - f - 1;
			ans = max(ans, j + 1);
			f[j] = a[i];
		}
	}
};
struct Manacher//马拉车求回文串
{
	string s, t;
	int ans, p[N];
	void manacher()
	{
		t = "$#";
		int n = s.size();
		for(int i = 0; i < n; ++i)
		{
			t += s[i];
			t += "#";
		}
		int mr = 0, mid = 0, m = t.size();
		for(int i = 1; i < m; ++i)
		{
			if(mr > i)
				p[i] = min(p[mid * 2 - i], mr - i);
			else p[i] = 1;
			while(t[i + p[i]] == t[i - p[i]])
				++p[i];
			if(mr < p[i] + i)
			{
				mr = p[i] + i;
				mid = i;
			}
			ans = max(ans, p[i]);
		}
		--ans;
	}
};
struct The_Diameter_Of_A_Tree//树的直径
{
	Chain_Forward_Star C;
	int dis[N];//到u点的距离
	int max_dis;
	int p;//最远点储存在p
	void dfs(int u, int f)//当前点,父亲
	{
		for(int i = C.head[u]; ~i; i = C.e[i].nxt)
		{
			int v = C.e[i].v, w = C.e[i].w;
			if(v == f) continue;
			dis[v] = dis[u] + w;
			if(dis[v] > max_dis)
			{
				max_dis = dis[v];
				p = v;
			}
			dfs(v, u);
		}
	}
	void find_diameter()//x,y是直径,max_dis为直径的长度
	{
		dfs(1, 0);
		int x = p;
		max_dis = 0;
		dis[p] = 0;
		dfs(x, -1);
	}
};
struct Divide_And_Conquer_Points//点分治
{
	Chain_Forward_Star C;
	int sum, root;//子树的大小,子树的重心。
	int dis[N];//某个节点到其子树中节点的距离
	int ask[1010], ans[1010];
	int dp[N], pd[100000010], siz[N];//dp 用于存储子树的最大不平衡度,pd 用于标记某个距离是否被当前子树覆盖,siz 存储子树的大小。
	int sta[N], top;
	int tmp[N];//临时存储距离值,用于后续处理
	int vis[N];
	void get_focus(int u, int f)//找到以 u 为根的子树的重心
	{
		dp[u] = 0, siz[u] = 1;
		for(int i = C.head[u]; ~i; i = C.e[i].nxt)
		{
			int v = C.e[i].v;
			if(v == f || vis[v]) continue;
			get_focus(v, u);
			siz[u] += siz[v];
			dp[u] = max(dp[u], siz[v]);
		}
		dp[u] = max(dp[u], sum - siz[u]);
		if(dp[u] < dp[root]) root = u;
	}
	void get_dis(int u, int f)//递归地计算从 u 到其子树中所有节点的距离,并将这些距离存储在 sta 栈中
	{
		sta[++top] = dis[u];
		for(int i = C.head[u]; ~i; i = C.e[i].nxt)
		{
			int v = C.e[i].v, w = C.e[i].w;
			if(v == f || vis[v]) continue;
			dis[v] = dis[u] + w;
			get_dis(v, u);
		}
	}
	void calc(int u)//遍历子树并计算距离,检查是否存在满足条件的路径。
	{
		int c = 0;
		for(int i = C.head[u]; ~i; i = C.e[i].nxt)
		{
			int v = C.e[i].v, w = C.e[i].w;
			if(vis[v]) continue;
			top = 0, dis[v] = w, get_dis(v, u);
			for(int j = top ; j >= 1; --j)
				for(int k = 1; k <= m; ++k)
					if(ask[k] >= sta[j])
						ans[k] |= pd[ask[k] - sta[j]];
			for(int j = top ; j >= 1; --j)
				tmp[++c] = sta[j], pd[sta[j]] = 1;
		}
		for(int i = 1; i <= c; i++)
			pd[tmp[i]] = 0;
	}
	void solve(int u)//以 u 为根的子树,遍历所有未访问的子树
	{
		vis[u] = pd[0] = 1;
		calc(u);
		for(int i = C.head[u]; ~i; i = C.e[i].nxt)
		{
			int v = C.e[i].v;
			if(vis[v]) continue;
			dp[0] = INT_MAX, sum = siz[v], root = 0;
			get_focus(v, 0), solve(root);
		}
	}
	void work()
	{
		cin >> n >> m;
		dp[0] = sum = n;
		for(int i = 1, u, v, w; i < n; ++i)
		{
			cin >> u >> v >> w;
			C.add_edge(u, v, w);
			C.add_edge(v, u, w);
		}
		for(int i = 1; i <= m; ++i)
			cin >> ask[i];
		get_focus(1, 0), solve(root);
		for(int i = 1; i <= m; ++i)
			cout << (ans[i] ? "yes\n" : "no\n");
	}
};
struct shuweiDP
{
	int a[30];//拆位数组
	int b;//b进制
	int dp[60][60];//记忆化数组,dp[pos]定义为在没有限制没有前导零的情况,从pos位开始填的答案
	//状态数随题目条件改变,一般不止一维,记得初始化为-1
	//pos表示还有几位要填
	//lim表示是否有最高位限制
	//lead表示是否填的数全是前导0,这里0也会被判成前导0,不过一般不影响结果
	//st是与题目相关的状态,数量和名字都依据题目变化
	int dfs(int pos, int st, int limit, int lead)
	{
		if(pos == 0) return 1;//递归到底层,满足要求就返回1
		if(!limit && !lead && dp[pos][st] != -1)
			return dp[pos][st];    //如果发现没有限制,不全是0且状态搜过则直接返回
		int up = limit ? a[pos] : b - 1;//当前位最高能填多少
		int ret = 0;
		for(int i = 0; i <= up; ++i)//一些与题目要求去条件的判断
			ret += dfs(pos - 1, st, limit && (i == up), lead && !i);
		return (!limit && !lead) ? dp[pos][st] = ret : ret;//如果发现没有限制,不全是0,则加入记忆化数组
	}
	int calc(int x)
	{
		if(!x) return 1;//把<=0的特判掉
		int len = 0;
		while(x) a[++len] = x % b, x /= b;
		return dfs(len, 0, 1, 1);
	}
};
template<typename T = int>class Monotonic_queue//区间最小值单调队列
{
  public:
  	int k;
  	struct node
	{
	  	int id;
	  	T val;
	};
	Monotonic_queue(int k_):k(k_) {de.clear();}
	node front() {return de.front();}
	node back() {return de.back();}
	void push_back(int id, int x)
	{
		while(!de.empty() && x >= de.back().val)
			de.pop_back();
		de.push_back(node{id, x});
		while(id - k >= de.front().id)
			de.pop_front();
	}
  private:
	deque<node> de;
};
template<typename T = int>class Sparse_Table//ST表
{
  public:
	Sparse_Table(int n_ = N - 1)
	{
		Log2[0] = Log2[1] = 0;
		for(int i = 2; i <= n_; ++i)
			Log2[i] = Log2[i >> 1] + 1;
	}
	void build_st(T *a) {Build_st(a);}
	T query(int l, int r) {return Query(l, r);}
  private:
	T st[N][32];//ST[i][j]表示以i为起点,(2^j)-1为长度的区间最大值
	int Log2[N];//减小log带来的常数
	void Build_st(T *a)
	{
		for(int i = 1; i <= n; ++i)
			st[i][0] = a[i];
		for(int i = 1; i <= Log2[n]; ++i)//先枚举区间长度
			for(int j = 1; j + ((1 << i) - 1) <= n; ++j)
				st[j][i] = max(st[j][i - 1], st[j + (1 << (i - 1))][i - 1]);
	}
	T Query(int l, int r)
	{
		int k = Log2[r - l + 1];
		return max(st[l][k], st[r - (1 << k) + 1][k]);
	}
};
template<typename T = int>class Segment_Tree//线段树
{
  public:
	void build_tree(T *a) {Build_tree(1, 1, n, a);}
	void modify_add(int x, int y, T v) {Modify(1, 1, n, x, y, v, 1);}
	void modify_mul(int x, int y, T v) {Modify(1, 1, n, x, y, v, 2);}
	void modify_cov(int x, int y, T v) {Modify(1, 1, n, x, y, v, 3);}
	T query(int x, int y) {return Query(1, 1, n, x, y);}
  private:
#define mid ((l + r) >> 1)
#define ls (p << 1)
#define rs (p << 1 | 1)
	struct node
	{
		T sum, max_val, min_val, add_tag, mul_tag, cov_tag;
		T lmax, rmax, maxn;//最大子段和
		node(): sum(0), max_val(-INF), min_val(INF), add_tag(0), mul_tag(1), cov_tag(-INF), lmax(0), rmax(0), maxn(0) {}
	} t[N << 2];
	void Apply_add(int p, int l, int r, T v)
	{
		t[p].sum += (r - l + 1) * v;
		t[p].add_tag += v;
		t[p].max_val += v;
		t[p].min_val += v;
	}
	void Apply_mul(int p, T v)
	{
		t[p].mul_tag *= v;
		t[p].add_tag *= v;
		t[p].sum *= v;
		t[p].max_val *= v;
		t[p].min_val *= v;
	}
	void Apply_cov(int p, int l, int r, T v)
	{
		t[p].cov_tag = v;
		t[p].sum = (r - l + 1) * v;
		t[p].max_val = v;
		t[p].min_val = v;
		t[p].add_tag = 0;
		t[p].mul_tag = 1;
	}
	void Push_up(int p)
	{
		t[p].sum = t[ls].sum + t[rs].sum;
		t[p].max_val = max(t[ls].max_val, t[rs].max_val);
		t[p].min_val = min(t[ls].min_val, t[rs].min_val);
		t[p].lmax = max(t[ls].lmax, t[ls].sum + t[rs].lmax);
		t[p].rmax = max(t[ls].rmax + t[rs].sum, t[rs].rmax);
		t[p].maxn = max(t[ls].maxn, t[rs].maxn, t[ls].rmax + t[rs].lmax);
	}
	void Push_down(int p, int l, int r)
	{
		if(t[p].cov_tag != -INF)
		{
			Apply_cov(ls, l, mid, t[p].cov_tag);
			Apply_cov(rs, mid + 1, r, t[p].cov_tag);
			t[p].cov_tag = -INF;
		}
		if(t[p].mul_tag != 1)
		{
			Apply_mul(ls, t[p].mul_tag);
			Apply_mul(rs, t[p].mul_tag);
			t[p].mul_tag = 1;
		}
		if(t[p].add_tag)
		{
			Apply_add(ls, l, mid, t[p].add_tag);
			Apply_add(rs, mid + 1, r, t[p].add_tag);
			t[p].add_tag = 0;
		}
	}
	void Build_tree(int p, int l, int r, T *a)//建树
	{
		if(l == r)
		{
			t[p].sum = a[l];
			t[p].max_val = a[l];
			t[p].min_val = a[l];
			t[p].lmax = a[l];
			t[p].rmax = a[l];
			t[p].maxn = a[l];
			return;
		}
		Build_tree(ls, l, mid, a);
		Build_tree(rs, mid + 1, r, a);
		Push_up(p);
	}
	void Modify(int p, int l, int r, int x, int y, T v, int flag)//区间加 ,乘 ,覆盖(1,2,3)
	{
		if(r < x || y < l) return;
		if(x <= l && r <= y)
		{
			if(flag == 1) Apply_add(p, l, r, v);
			if(flag == 2) Apply_mul(p, v);
			if(flag == 3) Apply_cov(p, l, r, v);
			return;
		}
		Push_down(p, l, r);
		if(x <= mid) Modify(ls, l, mid, x, y, v, flag);
		if(y > mid) Modify(rs, mid + 1, r, x, y, v, flag);
		Push_up(p);
	}
	T Query(int p, int l, int r, int x, int y)
	{
		if(r < x || y < l) return 0;
		if(x <= l && r <= y) return t[p].sum;
		Push_down(p, l, r);
		if(y <= mid) return Query(ls, l, mid, x, y);
		if(x > mid) return Query(rs, mid + 1, r, x, y);
		T res = 0;
		if(x <= mid) res += Query(ls, l, mid, x, y);
		if(y > mid) res += Query(rs, mid + 1, r, x, y);
		return res;
	}
#undef mid
#undef ls
#undef rs
};
template<typename T = int>class Dynamic_Segment_Tree//动态开点线段树
{
  public:
	Dynamic_Segment_Tree() {cnt = root = 1;}
	void modify_add(int x, int y, T v) {Modify(root, 1, n, x, y, v, 1);}
	void modify_mul(int x, int y, T v) {Modify(root, 1, n, x, y, v, 2);}
	void modify_cov(int x, int y, T v) {Modify(root, 1, n, x, y, v, 3);}
	T query(int x, int y) {return Query(root, 1, n, x, y);}
  private:
#define mid ((l + r) >> 1)
#define ls t[p].lson
#define rs t[p].rson
	struct node
	{
		int lson, rson;
		T sum, max_val, min_val, add_tag, mul_tag, cov_tag;
		T lmax, rmax, maxn;//最大子段和
		node(): sum(0), max_val(-INF), min_val(INF), add_tag(0), mul_tag(1), cov_tag(-INF), lson(0), rson(0), lmax(0), rmax(0), maxn(0) {}
	} t[N << 2];
	int cnt, root;
	int New_node() {return ++cnt;}
	void Apply_add(int p, int l, int r, T v)
	{
		t[p].sum += (r - l + 1) * v;
		t[p].add_tag += v;
		t[p].max_val += v;
		t[p].min_val += v;
	}
	void Apply_mul(int p, T v)
	{
		t[p].mul_tag *= v;
		t[p].add_tag *= v;
		t[p].sum *= v;
		t[p].max_val *= v;
		t[p].min_val *= v;
	}
	void Apply_cov(int p, int l, int r, T v)
	{
		t[p].cov_tag = v;
		t[p].sum = (r - l + 1) * v;
		t[p].max_val = v;
		t[p].min_val = v;
		t[p].add_tag = 0;
		t[p].mul_tag = 1;
	}
	void Push_up(int p)
	{
		t[p].sum = t[ls].sum + t[rs].sum;
		t[p].max_val = max(t[ls].max_val, t[rs].max_val);
		t[p].min_val = min(t[ls].min_val, t[rs].min_val);
		t[p].lmax = max(t[ls].lmax, t[ls].sum + t[rs].lmax);
		t[p].rmax = max(t[ls].rmax + t[rs].sum, t[rs].rmax);
		t[p].maxn = max(t[ls].maxn, t[rs].maxn, t[ls].rmax + t[rs].lmax);
	}
	void Push_down(int p, int l, int r)
	{
		if(!ls) ls = New_node();
		if(!rs) rs = New_node();
		if(t[p].cov_tag != -INF)
		{
			Apply_cov(ls, l, mid, t[p].cov_tag);
			Apply_cov(rs, mid + 1, r, t[p].cov_tag);
			t[p].cov_tag = -INF;
		}
		if(t[p].mul_tag != 1)
		{
			Apply_mul(ls, t[p].mul_tag);
			Apply_mul(rs, t[p].mul_tag);
			t[p].mul_tag = 1;
		}
		if(t[p].add_tag)
		{
			Apply_add(ls, l, mid, t[p].add_tag);
			Apply_add(rs, mid + 1, r, t[p].add_tag);
			t[p].add_tag = 0;
		}
	}
	void Modify(int p, int l, int r, int x, int y, T v, int flag)//区间加,乘,覆盖(1,2,3)
	{
		if(r < x || y < l) return;
		if(x <= l && r <= y)
		{
			if(flag == 1) Apply_add(p, l, r, v);
			if(flag == 2) Apply_mul(p, v);
			if(flag == 3) Apply_cov(p, l, r, v);
			return;
		}
		Push_down(p, l, r);
		if(x <= mid) Modify(ls, l, mid, x, y, v, flag);
		if(y > mid) Modify(rs, mid + 1, r, x, y, v, flag);
		Push_up(p);
	}
	T Query(int p, int l, int r, int x, int y)
	{
		if(r < x || y < l) return 0;
		if(x <= l && r <= y) return t[p].sum;
		Push_down(p, l, r);
		if(y <= mid) return Query(ls, l, mid, x, y);
		if(x > mid) return Query(rs, mid + 1, r, x, y);
		T res = 0;
		if(x <= mid) res += Query(ls, l, mid, x, y);
		if(y > mid) res += Query(rs, mid + 1, r, x, y);
		return res;
	}
#undef mid
#undef ls
#undef rs
};
template<typename T = int>class Rotate_Treap//旋转Treap
{
	//千万别乱用
  public:
	Rotate_Treap() {Build_treap();}
	void insert(T val) {Insert(root, val);}
	void remove(T val) {Remove(root, val);}
	int get_rank(T val) {return Get_rank(root, val);}
	T get_val(int k) {return Get_val(root, k);}
	T get_pre(T val) {return Get_pre(val);}
	T get_next(T val) {return Get_next(val);}
  private:
#define ls(p) t[p].lson
#define rs(p) t[p].rson
	int root, cnt;
	struct node
	{
		int lson, rson;//左右儿子
		T val, key;//值,优先级(随机)
		int tot, size;//值的个数,子树大小
		node(): lson(0), rson(0), val(0), key(0), tot(0), size(0) {}
	} t[N];
	int New_node(T val)//创建值为val的新节点
	{
		t[++cnt].val = val;
		t[cnt].key = rand();//优先级随机
		t[cnt].tot = t[cnt].size = 1;
		return cnt;//返回节点编号
	}
	void Push_up(int p)//更新节点子树大小
	{
		t[p].size = t[ls(p)].size + t[ls(p)].size + t[p].tot;//节点子树的大小=左子树+右子树+当前节点值的个数
	}
	void Build_treap()//建树堆
	{
		New_node(-INF);
		New_node(INF);
		root = 1, rs(root) = 2;
		Push_up(root);
	}
	void Rotate_r(int &p)//右旋
	{
		int q = ls(p);
		ls(p) = rs(q);
		rs(q) = p;
		p = q;
		Push_up(rs(q));
		Push_up(p);
	}
	void Rotate_l(int &p)//左旋
	{
		int q = rs(p);
		rs(p) = ls(q);
		ls(q) = p;
		p = q;
		Push_up(ls(p));
		Push_up(p);
	}
	void Insert(int &p, T val)//插入值为val的新节点
	{
		if(!p)//子树为空,新建
		{
			p = New_node(val);
			return;
		}
		if(val == t[p].val)//如果值和当前节点相同
		{
			t[p].tot++;//个数加1就好
			Push_up(p);//更新当前子树大小
			return;
		}
		if(val < t[p].val)
		{
			Insert(ls(p), val);//要插到左边
			if(t[p].key < t[ls(p)].key)//如果优先级不满足
				Rotate_r(p);    //右旋
		}
		else
		{
			Insert(rs(p), val);//要插到右边
			if(t[p].key < t[rs(p)].key)//如果优先级不满足
				Rotate_l(p);    //左旋
		}
		Push_up(p);//更新节点子树大小
	}
	void Remove(int &p, T val)//删除1个值为val的节点
	{
		if(!p) return;//如果为空直接返回
		if(val == t[p].val)//找到值为val的节点
		{
			if(t[p].tot > 1)//如果个数超过一个
			{
				--t[p].tot;//直接把个数减1
				Push_up(p);//更新当前节点的子树大小
				return;
			}
			if(ls(p) || rs(p))//如果存在子树
			{
				if(rs(p) == 0 || t[ls(p)].key > t[rs(p)].key)
					Rotate_r(p), Remove(rs(p), val);    //右旋
				else Rotate_l(p), Remove(ls(p), val);//左旋
				Push_up(p);//更新子树大小
			}
			else p = 0;//到叶子节点
			return;
		}
		val <= t[p].val ? Remove(ls(p), val) : Remove(rs(p), val);//递归查找要删除的数的位置
		Push_up(p);//更新当前节点子树大小
	}
	int Get_rank(int p, T val)//询问排名
	{
		if(!p) return 0;//如果节点为空返回0
		if(val == t[p].val)
			return t[ls(p)].size + 1;    //左儿子都比他小
		if(val < t[p].val)
			return Get_rank(ls(p), val);    //去左子树里面查找
		return Get_rank(rs(p), val) + t[ls(p)].size + t[p].tot;//同时左子树个数+当前节点个数比他小
	}
	T Get_val(int p, int k)//询问排名第k
	{
		if(!p) return INF;//如果节点为空返回INF
		if(t[ls(p)].size >= k)
			return Get_val(ls(p), k);    //继续向左查找
		if(t[ls(p)].size + t[p].tot >= k)
			return t[p].val;    //当前节点就是第k大的数
		return Get_val(rs(p), k - t[ls(p)].size - t[p].tot);//在右子树里找剩下的
	}
	T Get_pre(T val)//询问前驱
	{
		T res = -INF;
		int p = root;
		while(p)
		{
			if(val >= t[p].val)
			{
				res = t[p].val;
				p = rs(p);
			}
			else p = ls(p);
		}
		return res;
	}
	T Get_next(T val)//询问后继
	{
		T res = INF;
		int p = root;
		while(p)
		{
			if(val <= t[p].val)
			{
				res = t[p].val;
				p = ls(p);
			}
			else p = rs(p);
		}
		return res;
	}
};
template<typename T = int>class FHQ_Treap//范浩强无旋Treap
{
  public:
	FHQ_Treap() {Build_treap();}
	void insert(T val) {Insert(val);}
	void remove(T val) {Remove(val);}
	int get_rank(T val) {return Get_rank(val);}
	T get_val(int k) {return Get_val(root, k);}
	T get_pre(T val) {return Get_pre(val);}
	T get_next(T val) {return Get_next(val);}
  private:
	int root, cnt;
	struct node
	{
		int lson, rson;//左右儿子
		T val, key;//值,优先级(随机)
		int size;//子树大小
		node(): lson(0), rson(0), val(0), key(0), size(0) {}
	} t[N];
	int New_node(T val)//创建值为val的新节点
	{
		int x = ++cnt;
		ls(x) = rs(x) = 0;
		t[x].size = 1;
		t[x].val = val;
		t[x].key = rand();//随机优先级
		return x;//返回节点编号
	}
	void Build_treap()
	{
		New_node(INF);
		New_node(-INF);
		root = 1, rs(root) = 2;
		Push_up(root);
	}
	void Push_up(int p)//更新节点子树大小
	{
		if(!p) return;
		t[p].size = t[ls(p)].size + t[rs(p)].size + 1;
	}
	void Split_by_val(int p, T k, int &x, int &y)//将p子树以按k拆成x和y子树,其中x中的点<=k,y中全部大于k
	{
		if(!p)
		{
			x = y = 0;//分裂到头了
			return;
		}
		if(t[p].val <= k)//当前节点小,放x上
		{
			x = p;//x上暂时放的p子树,还要去看p的右子树
			Split_by_val(rs(p), k, rs(p), y);//去看p右子树,如果有<key的则应该保留在p右子树上(最后给x),否则放在y上
		}
		else
		{
			y = p;
			Split_by_val(ls(p), k, x, ls(p));//去看p左子树,如果有>=key的则应该放在p左子树上(最后给y),否则放在x上
		}
		Push_up(p);//防止更新0点
	}
	int Merge(int x, int y)//合并x,y子树,其中x子树的值<=y子树的值,返回根节点
	{
		if(!x || !y) return x | y;//x如果有一个子树为空则返回另一个子树
		if(t[x].key > t[y].key)//x在堆中是在y的上方,而值小于y,故在y的左上方
		{
			rs(x) = Merge(rs(x), y);//让x的右子树和y合并
			Push_up(x);
			return x;
		}
		else//x在y的左下方
		{
			ls(y) = Merge(x, ls(y));//x和y的左子树合并
			Push_up(y);
			return y;
		}
	}
	void Insert(T val)//插入值为val的节点
	{
		int x, y;
		Split_by_val(root, val, x, y);
		root = Merge(Merge(x, New_node(val)), y);
	}
	void Remove(T val)//删除值为val的节点
	{
		int x, y, z;
		Split_by_val(root, val, x, z);//把root为根节点的树分为AB两棵树,<=val的A树树根为x,B树树根z
		Split_by_val(x, val - 1, x, y);//把x为根节点的树分为CD两棵树,<=val-1的C树树根为x,D树树根y,x<=val,再分x <= val- 1,y就是=val的树
		y = Merge(ls(y), rs(y));//直接让y树的左右儿子进行合并,忽略y节点,删除y点
		root = Merge(Merge(x, y), z);//先把CD合并,再与原来的B树进行合并
	}
	int Get_rank(T val)//按值查排名
	{
		int x, y;
		Split_by_val(root, val - 1, x, y);//按val-1分割,x子树大小+1就是排名
		val = t[x].size + 1;//储存x的大小+1
		root = Merge(x, y);//重新把x,y子树合并,还原root
		return val;
	}
	T Get_val(int p, int k)//按排名查值
	{
		int tmp = t[ls(p)].size + 1;//当前节点排名tmp=他的左子树节点个数+1
		if(tmp == k)
			return t[p].val;    //刚好等于k,即为找到了
		if(tmp > k)
			return Get_val(ls(p), k);    //说明应该在左子树里继续寻找
		return Get_val(rs(p), k - tmp);//说明已经找到tmp个比他小的,再继续找k-tmp
	}
	T Get_pre(T val)//查询前驱
	{
		int x, y;
		T res;
		Split_by_val(root, val - 1, x, y);
		res = Get_val(x, t[x].size);//然后找A树内的最大值(即在A树内查询排名为 size 的数值)
		root = Merge(x, y);
		return res;
	}
	T Get_next(T val)//查询后继
	{
		int x, y;
		T res;
		Split_by_val(root, val, x, y);
		res = Get_val(y, 1);//然后找B树内的最小值即在B树内查询排名为1的数值
		root = Merge(x, y);
		return res;
	}
};
//优化,精简,改进,模板化,改写为class
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	system("taskkill /f /t /im studentmain.exe");
	return 0;
}
posted @ 2024-08-07 11:50  Rich1  阅读(4)  评论(0)    收藏  举报