全RE
查看原帖
全RE
701221
Chr0n1CleC楼主2022/8/28 21:26
#include<stdio.h>
#define N 100009

struct Splay
{
	int rt, tot, cnt[N], val[N], fa[N], ch[N][2], siz[N];
	inline void updata(int x)
	{
		siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
	}
	inline bool get(int x)
	{
		return x == ch[fa[x]][1];
	}
	inline void clear(int x)
	{
		cnt[x] = val[x] = fa[x] = ch[x][0] = ch[x][1] = siz[x] = 0;
	}
	inline void rorate(int x)
	{
		int y = fa[x], z = fa[y], f = get(x);
		ch[y][f] = ch[x][!f];
		if (ch[x][!f])
			fa[ch[x][!f]] = y;
		ch[x][!f] = y;
		fa[y] = x;
		fa[x] = z; 
		if (z)
			ch[z][y == ch[z][1]] = x;
		updata(x), updata(y);
	}
	inline void splay(int x, int root = 0)
	{
		while (fa[x] != root)
		{
			//			if (get(x) == get(fa[x]))//三点共线 
			//				rorate(fa[x]);//先旋转父节点 
			rorate(x);//再旋转子节点 
		}
		if (!root)
			rt = x;//如果时旋转到根,那么根就是 x了 
	}
	inline void insert(int x)
	{
		if (!rt)
		{
			rt = ++ tot;
			val[tot] = x;
			cnt[tot] = 1;//构建新点 
			updata(rt);
			return;
		}//树都没有 
		int cur = rt, f = 0;
		while (1)
		{
			if (val[cur] == x)
			{
				cnt[cur] ++;
				updata(cur);
				updata(f);
				splay(cur);
				return;
			}//重复 
			f = cur;
			cur = ch[cur][val[cur] < x];
			if (!cur)
			{
				ch[f][val[f] < x] = ++ tot;//构建关系 
				fa[tot] = f;//构建关系 
				val[tot] = x;
				cnt[tot] = 1;
				updata(tot);
				updata(f);
				splay(tot);//规定操作完都得splay上去
				return;
			}//到了地方了 
		}
	}
	inline int nxt()
	{
		int cur = ch[rt][1];
		if (!cur)
			return cur;
		while (ch[cur][0])//一直跳 
			cur = ch[cur][0];
		splay(cur);
		return cur;
	}
	inline int pre()
	{
		int cur = ch[rt][0];
		if (!cur)
			return cur;
		while (ch[cur][1])
			cur = ch[cur][1];
		splay(cur);
		return cur; 
	}//同理 
	inline int rank(int x)
	{
		int cur = rt, ret = 0;
		while (cur)
		{
			if (x < val[cur])
				cur = ch[cur][0];
			else
			{
				ret += siz[ch[cur][0]];
				if (x == val[cur])
				{
					splay(cur);
					return ret + 1;
				}
				ret += cnt[cur];
				cur = ch[cur][1];
			}
		}
	}//查找x的排名 
	inline void del(int x)
	{
		rank(x);
		if (cnt[rt] > 1)
		{
			cnt[rt] --, siz[rt] --;
			return;
		}
		if (!ch[rt][0] && !ch[rt][1])
		{
			clear(rt);
			rt = 0;
			return;
		}
		if (!ch[rt][0])
		{
			int cur = rt;
			rt = ch[rt][1];
			fa[rt] = 0;
			clear(cur);
			return;
		}
		if (!ch[rt][1])
		{
			int cur = rt;
			rt = ch[rt][0];
			fa[rt] = 0;
			clear(cur);
			return;
		}
		int cur = rt, k = pre();
		fa[ch[cur][1]] = k;
		ch[k][1] = ch[cur][1];
		clear(cur);
		updata(rt);
	}
	inline int xrank(int x)
	{
		int cur = rt;
		while (1)
		{
			if (ch[cur][0] && x <= siz[ch[cur][0]])
				cur = ch[cur][0];
			else
			{
				x -= siz[ch[cur][0]] + cnt[cur];
				if (x <= 0)
				{
					splay(cur);
					return val[cur];
				}
				cur = ch[cur][1];
			}
		}
	}//查找排名为x的数 
}T;

//图信息-----------------------------------------------------

int a[N], rt;

struct node
{
	int v, nxt;
}e[N << 1];

int head[N], cnt;

int dfn[N], tot[N], b[N], deep[N], top[N], fa[N], siz[N], hson[N];


void dfs1(int u, int fath)
{
	fa[u] = fath;
	deep[u] = deep[fath] + 1;
	siz[u] = 1;
	hson[u] = -1;
	for (int i = head[u];i;i = e[i].nxt)
		if (e[i].v != fath)
	{
		dfs1(e[i].v, u);
		siz[u] += siz[e[i].v];
		if (hson[u] == -1 || siz[e[i].v] > siz[hson[u]])
			hson[u] = e[i].v;
	}
}

void dfs2(int u, int Top)
{
	top[u] = Top;
	dfn[u] = ++ cnt;
	b[cnt] = a[u];
	if (hson[u] == -1)
		return;
	dfs2(hson[u], Top);
	for (int i = head[u];i;i = e[i].nxt)
		if (e[i].v != hson[u] && e[i].v != fa[u])
			dfs2(e[i].v, e[i].v);
}

inline void add(int u, int v)
{
	e[++ cnt].v = v, e[cnt].nxt = head[u], head[u]=  cnt;
}

//图信息-----------------------------------------------

//线段树-----------------------------------------------

int tree[N << 2], lazy[N << 2];

#define ls (p << 1)
#define rs (ls + 1)

void build(int l, int r, int p)
{
	if (l == r)
	{
		tree[p] = b[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(l, mid, ls);
	build(mid + 1, r, rs);
	tree[p] = tree[ls] + tree[rs];
}

inline void pushdown(int l, int r, int p)
{
	lazy[ls] += lazy[p];
	lazy[rs] += lazy[p];
	int mid = (l + r) >> 1;
	tree[ls] += lazy[ls] * (mid - l + 1);
	tree[rs] += lazy[rs] * (r - mid);
}

void change(int sl, int sr, int l, int r, int p, int k)
{
	if (l >= sl && r <= sr)
	{
		tree[p] += (r - l + 1) * k;
		lazy[p] += k;
		return;
	}
	pushdown(l, r, p);
	int mid = (l + r) >> 1;
	if (sl <= mid)
		change(sl, sr, l, mid, ls, k);
	if (sr > mid)
		change(sl, sr, mid + 1, r, rs, k);
	tree[p] = tree[ls] + tree[rs];
}

int query(int sl, int sr, int l, int r, int p)
{
	if (l >= sl && r <= sr)
		return tree[p];
	pushdown(l, r, p);
	int mid = (l + r) >> 1, ret = 0;
	if (sl <= mid)
		ret = query(sl, sr, l, mid, ls);
	if (sr > mid)
		ret += query(sl, sr, mid + 1, r, rs);
	return ret;
}

//线段树-----------------------------------------------

//树剖

int n;

inline void swap(int& a, int& b) {a ^= b,  b ^= a, a ^= b;}

inline void Change(int u, int A)
{
	change(u, u, 1, n, 1, A);
}

inline void Change1(int u, int A)
{
	change(dfn[u], dfn[u] + siz[u] - 1, 1, n, 1, A);
}

inline void Query(int u)
{
	int ans = 0;
	int v = 1;
	while (top[u] != top[v])
	{
		if (deep[u] < deep[v])
			swap(u, v);
		ans += query(dfn[top[u]], dfn[u], 1, n, 1);
		u = fa[top[u]];
	}
	if (dfn[u] > dfn[v])
		swap(u, v);
	printf("%d\n", ans + query(dfn[u], dfn[v], 1, n, 1));
}

//树剖

int main()
{
	int m;
	scanf("%d%d", &n, &m);
	for (int i = 1;i <= n;i ++)
		scanf("%d", &a[i]);
	int u, v;
	for (int i = 1;i < n;i ++)
		scanf("%d%d", &u, &v), add(u, v), add(v, u);
	dfs1(1, 0);
	dfs2(1, 1);
	build(1, n, 1);
	int opt;
	while (m --)
	{
		scanf("%d%d", &opt, &u);
		if (opt == 1)
			scanf("%d", &v), Change(u, v);
		if (opt == 2)
			scanf("%d", &v), Change1(u, v);
		if (opt == 3)
			Query(u);
	}
	
	return 0;
}
2022/8/28 21:26
加载中...