树剖杂题

P3128 [USACO15DEC] Max Flow P

树链剖分\(lca\)+树上差分

对于点权的差分 就是\(s,t\)位置增加 \(lca(s,t)\&fa[lca(s,t)]\)位置减少

最后做一遍树上前缀和即可

错误:\(dfs2\)\(tp\)写成了\(u\)

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
const int N = 3e5 + 5;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , dep[N] , sz[N] , fa[N] , son[N] , top[N] , a[N] , maxx;

vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }

struct LCA 
{
	void dfs1 ( int u , int f )
	{
		dep[u] = dep[f] + 1 , fa[u] = f , sz[u] = 1;
		for ( auto v : e[u] )
			if ( v ^ f )
			{
				dfs1 ( v , u );
				sz[u] += sz[v];
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}
	void dfs2 ( int u , int tp )
	{
		top[u] = tp;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto v : e[u] ) if ( v ^ fa[u] && v ^ son[u] ) dfs2 ( v , v );
	}
	int lca ( int u , int v )
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		return v;
	}
}L;

void dfs ( int u , int f )
{
	for ( auto v : e[u] ) if ( v ^ f ) dfs ( v , u ) , a[u] += a[v];
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr) , cout.tie(nullptr);
	n = read() , m = read();
	for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
	L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 );
	for ( int i = 1 , x , y ; i <= m ; i ++ )
	{
		int s = read() , t = read();
		a[s] ++ , a[t] ++;
		a[L.lca(s,t)] -- , a[fa[L.lca(s,t)]] --;
	}
	dfs ( 1 , 0 );
	for ( int i = 1 ; i <= m ; i ++ ) maxx = max ( maxx , a[i] );
	cout << maxx << endl;
	return 0;
}

P3038 [USACO11DEC] Grass Planting G

边权转点权板子 码力得到提升=v=

注意在最后查询的时候顶端的\(lca\)节点需要忽略 具体操作即为\(query ( 1 , 1 , n , pos[v] + 1 , pos[u] );\)

线段树中也需要特判\(x>y\)的情况捏()

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
const int N = 3e5 + 5;
// char buf[1<<24] , *p1 , *p2;
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , a[N];
int dep[N] , sz[N] , fa[N] , son[N];
int top[N] , timer , pos[N] , rev[N];

vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }

struct LCA 
{
	void dfs1 ( int u , int f )
	{
		dep[u] = dep[f] + 1 , fa[u] = f , sz[u] = 1;
		for ( auto v : e[u] )
			if ( v ^ f )
			{
				dfs1 ( v , u ) , a[v] = 1 , sz[u] += sz[v];
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}
	void dfs2 ( int u , int tp )
	{
		top[u] = tp , pos[u] = ++timer , rev[timer] = u;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto v : e[u] ) if ( v ^ fa[u] && v ^ son[u] ) dfs2 ( v , v );
	}
}L;

struct seg
{
	struct node { int sum , add; } t[N<<2];
	inl void up ( int p ) { t[p].sum = t[ls].sum + t[rs].sum; } 
	inl void pushadd ( int p , int l , int r , int val ) { t[p].sum += ( r - l + 1 ) * val , t[p].add += val; }
	inl void down ( int p , int l , int r ) { if ( t[p].add ) pushadd ( lson , t[p].add ) , pushadd ( rson , t[p].add ) , t[p].add = 0; }
	void build ( int p , int l , int r )
	{
		if ( l == r ) return t[p].sum = a[rev[l]] , void();
		build ( lson ) , build ( rson ) , up(p);
	}
	void upd ( int p , int l , int r , int x , int y , int val )
	{
		if ( x > y ) return;
		if ( x <= l && r <= y ) return pushadd ( p , l , r , val ) , void();
		down ( p , l , r );
		if ( x <= mid ) upd ( lson , x , y , val );
		if ( mid + 1 <= y ) upd ( rson , x , y , val );
		up(p);
	}
	int query ( int p , int l , int r , int x , int y )
	{
		if ( x > y ) return 0;
		if ( x <= l && r <= y ) return t[p].sum;
		int res = 0; down ( p , l , r );
		if ( x <= mid ) res += query ( lson , x , y );
		else res += query ( rson , x , y );
		return res;
	}
	void updsum ( int u , int v )
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			upd ( 1 , 1 , n , pos[top[u]] , pos[u] , 1 );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		upd ( 1 , 1 , n , pos[v] + 1 , pos[u] , 1 );
	}
	int querysum ( int u , int v )
	{
		int sum = 0;
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			sum += query ( 1 , 1 , n , pos[top[u]] , pos[u] );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		sum += query ( 1 , 1 , n , pos[v] + 1 , pos[u] );
		return sum;
	}
}T;

char op;
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , m = read();
	for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
	L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 );
	for ( int i = 1 , u , v ; i <= m ; i ++ )
	{
		cin >> op , u = read() , v = read();
		if ( op == 'P' ) T.updsum ( u , v );
		else cout << T.querysum ( u , v ) << endl;
	}
	return 0;
}

P4427 [BJOI2018] 求和

对于\(k\)次方和 维护一个\(pre[i][j]\)表示第\(i\)个节点到根节点的路径上的所有深度的\(j\)次方和 因为\(k\)很小 所以可以暴力用快速幂改

注意这里的\(dep[0]=-1\) 才能保证根节点的\(dep=0\)

减法有可能出现负数 加一个\(mod\)即可

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define int long long 
const int N = 3e5 + 5;
const int mod = 998244353;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
// #define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , dep[N] , fa[N] , sz[N] , son[N] , top[N] , pre[N][51];

vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }

int ksm ( int base , int k )
{
	int res = 1;
	for ( ; k ; ( base *= base ) %= mod , k >>= 1 )
		if ( k & 1 ) ( res *= base ) %= mod;
	return res;
}

struct LCA 
{
	void dfs1 ( int u , int f )
	{
		dep[u] = dep[f] + 1 , fa[u] = f , sz[u] = 1;
		for ( int i = 0 ; i <= 50 ; i ++ ) ( pre[u][i] = pre[f][i] + ksm ( dep[u] , i ) ) %= mod;
		for ( auto v : e[u] )
			if ( v ^ f )
			{
				dfs1 ( v , u );
				sz[u] += sz[v];
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}
	void dfs2 ( int u , int tp )
	{
		top[u] = tp;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto v : e[u] ) if ( v ^ fa[u] && v ^ son[u] ) dfs2 ( v , v );
	}
	int lca ( int u , int v )
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		return v;
	}
}L;


signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read();
	for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
	m = read() , dep[0] = -1;
	L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 );
	for ( int i = 1 , u , v , k ; i <= m ; i ++ )
	{
		u = read() , v = read() , k = read();
		cout << ( pre[u][k] + pre[v][k] - pre[L.lca(u,v)][k] + mod - pre[fa[L.lca(u,v)]][k] + mod ) % mod << endl;
	}
	return 0;
}

P6098 [USACO19FEB] Cow Land G

简单题 树剖+单点修改区间查询线段树

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
const int N = 5e5 + 5;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
// #define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , q , a[N];

int fa[N] , dep[N] , sz[N] , son[N];
int timer , pos[N] , top[N] , rev[N];

vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }

struct LCA
{
	void dfs1 ( int u , int f )
	{
		fa[u] = f , sz[u] = 1 , dep[u] = dep[f] + 1;
		for ( auto v : e[u] )
			if ( v ^ f )
			{
				dfs1 ( v , u );
				sz[u] += sz[v];
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}
	void dfs2 ( int u , int tp )
	{
		top[u] = tp , pos[u] = ++timer , rev[timer] = u;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto v : e[u] ) if ( v ^ fa[u] && v ^ son[u] ) dfs2 ( v , v );
	}
}L;

struct Tree
{
	struct node { int sum; } t[N<<2];
	inl void up ( int p ) { t[p].sum = t[ls].sum ^ t[rs].sum; }
	void build ( int p , int l , int r )
	{
		if ( l == r ) return t[p].sum = a[rev[l]] , void();
		build ( lson ) , build ( rson ) , up(p);
	}
	void upd ( int p , int l , int r , int x , int val )
	{
		if ( l == r ) return t[p].sum = val , void();
		if ( x <= mid ) upd ( lson , x , val );
		else upd ( rson , x , val );
		up(p);
	}
	int query ( int p , int l , int r , int x , int y )
	{
		if ( x > y ) return 0;
		if ( x <= l && r <= y ) return t[p].sum;
		int res = 0;
		if ( x <= mid ) res ^= query ( lson , x , y );
		if ( mid + 1 <= y ) res ^= query ( rson , x , y );
		return res;
	}
	int querysum ( int u , int v )
	{
		int res = 0;
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			res ^= query ( 1 , 1 , n , pos[top[u]] , pos[u] );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		res ^= query ( 1 , 1 , n , pos[v] , pos[u] );
		return res;
	}
}T;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , q = read();
	for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
	for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
	L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 ) , T.build ( 1 , 1 , n );
	for ( int i = 1 ; i <= q ; i ++ )
	{
		int op = read() , u = read() , v = read();
		if ( op == 1 ) T.upd ( 1 , 1 , n , pos[u] , v );
		else cout << T.querysum ( u , v ) << endl;
	}
	return 0;
}

P4315 月下“毛景树”

码量 \(max\) 调试 \(max\) 但还是很板子() 注意线段树下传标记的时候要先下传\(cov\)再下传\(add\)

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define int long long 
const int N = 1e5 + 5;
// char buf[1<<24] , *p1 , *p2;
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , a[N] , x[N] , y[N] , w[N];

vector<pii> e[N];
inl void add ( int u , int v , int w ) { e[u].eb(v,w); }

int dep[N] , sz[N] , son[N] , fa[N];
int pos[N] , timer , top[N] , rev[N];

struct LCA
{
	void dfs1 ( int u , int f )
	{
		dep[u] = dep[f] + 1 , fa[u] = f , sz[u] = 1;
		for ( auto [v,w] : e[u] )
			if ( v ^ f )
			{
				dfs1 ( v , u );
				sz[u] += sz[v] , a[v] = w;
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}
	void dfs2 ( int u , int tp )
	{
		top[u] = tp , pos[u] = ++timer , rev[timer] = u;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto [v,w] : e[u] ) if ( v ^ fa[u] && v ^ son[u] ) dfs2 ( v , v );
	}
}L;

struct segtree
{
	struct node { int maxx , cov , add; } t[N<<2];
	inl void up ( int p ) { t[p].maxx = max ( t[ls].maxx , t[rs].maxx ); }
	inl void pushcov ( int p , int val ) { t[p].maxx = val , t[p].cov = val , t[p].add = 0; }
	inl void pushadd ( int p , int val ) { t[p].maxx += val , t[p].add += val; }
	inl void down ( int p )
	{
		if ( t[p].cov != -1 ) pushcov ( ls , t[p].cov ) , pushcov ( rs , t[p].cov ) , t[p].cov = -1;
		if ( t[p].add ) pushadd ( ls , t[p].add ) , pushadd ( rs , t[p].add ) , t[p].add = 0; 
	}
	void build ( int p , int l , int r )
	{
		t[p].cov = -1;
		if ( l == r ) return t[p].maxx = a[rev[l]] , void();
		build ( lson ) , build ( rson ) , up(p);
	}
	void upd ( int p , int l , int r , int x , int val )
	{
		if ( l == r ) return t[p].maxx = val , void();
		down(p);
		if ( x <= mid ) upd ( lson , x , val );
		else upd ( rson , x , val );
		up(p);
	}
	
	void cover ( int p , int l , int r , int x , int y , int val )
	{
		if ( x <= l && r <= y ) return pushcov ( p , val ) , void();
		down(p);
		if ( x <= mid ) cover ( lson , x , y , val );
		if ( mid + 1 <= y ) cover ( rson , x , y , val );
		up(p);
	}
	void coversum ( int u , int v , int val )
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			cover ( 1 , 1 , n , pos[top[u]] , pos[u] , val );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		cover ( 1 , 1 , n , pos[v] + 1 , pos[u] , val );
	}

	void add ( int p , int l , int r , int x , int y , int val )
	{
		if ( x <= l && r <= y ) return pushadd ( p , val ) , void();
		down(p);
		if ( x <= mid ) add ( lson , x , y , val );
		if ( mid + 1 <= y ) add ( rson , x , y , val );
		up(p);
	}
	void addsum ( int u , int v , int val )
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			add ( 1 , 1 , n , pos[top[u]] , pos[u] , val );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		add ( 1 , 1 , n , pos[v] + 1 , pos[u] , val );
	}

	int query ( int p , int l , int r , int x , int y )
	{
		if ( x > y ) return 0;
		if ( x <= l && r <= y ) return t[p].maxx;
		int res = 0; down(p);
		if ( x <= mid ) res = max ( res , query ( lson , x , y ) );
		if ( mid + 1 <= y ) res = max ( res , query ( rson , x , y ) );
		return res;
	}
	int maxx ( int u , int v )
	{
		int res = 0;
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			res = max ( res , query ( 1 , 1 , n , pos[top[u]] , pos[u] ) );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		res = max ( res , query ( 1 , 1 , n , pos[v] + 1 , pos[u] ) );
		return res; 
	}
}T;

string s;
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read();
	for ( int i = 1 ; i < n ; i ++ ) x[i] = read() , y[i] = read() , w[i] = read() , add ( x[i] , y[i] , w[i] ) , add ( y[i] , x[i] , w[i] );
	L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 ) , T.build ( 1 , 1 , n );
	while(1)
	{
		cin >> s;
		if ( s == "Stop" ) break;
		int u = read() , v = read();
		switch ( s[1] )
		{
			case 'a' : cout << T.maxx ( u , v ) << endl; break;
			case 'h' : T.upd ( 1 , 1 , n , pos[max(x[u],y[u])] , v ); break;
			case 'd' : T.addsum ( u , v , read() ); break;
			case 'o' : T.coversum ( u , v , read() ); break;
		}
	}
	return 0;
}

P4092 [HEOI2016/TJOI2016] 树

非常板的树剖 但预处理\(dep\)不当导致调试半小时

相当于是每次将某一个点打上标记(也就是将这个点的\(maxx\)改为深度) 那么对于一次询问 询问的是这条链上的最大深度 如果是\(0\)就说明没有标记点 继续向上跳 否则直接返回最大深度对应的节点编号

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
const int N = 1e5 + 5;
// char buf[1<<24] , *p1 , *p2;
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , a[N];

vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }

int dep[N] , fa[N] , sz[N] , son[N];
int top[N] , timer , pos[N] , rev[N];

struct LCA 
{
	void dfs1 ( int u , int f )
	{
		dep[u] = dep[fa[u] = f] + 1 , sz[u] = 1;
		for ( auto v : e[u] )
			if ( v ^ f )
			{
				dfs1 ( v , u );
				sz[u] += sz[v];
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}		
	void dfs2 ( int u , int tp )
	{
		top[u] = tp , pos[u] = ++timer , rev[timer] = u;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto v : e[u] ) if ( v ^ fa[u] && v ^ son[u] ) dfs2 ( v , v );
	}
}L;

struct tree
{
	struct node { int maxx = 0; } t[N<<2];
	inl void up ( int p ) { t[p].maxx = max ( t[ls].maxx , t[rs].maxx ); }
	void upd ( int p , int l , int r , int x )
	{
		if ( l == r ) return t[p].maxx = x , void();
		if ( x <= mid ) upd ( lson , x );
		else upd ( rson , x );
		up(p);
	}

	int query ( int p , int l , int r , int x , int y )
	{
		if ( x <= l && r <= y ) return t[p].maxx;
		int maxx = 0;
		if ( x <= mid ) maxx = max ( maxx , query ( lson , x , y ) );
		if ( mid + 1 <= y ) maxx = max ( maxx , query ( rson , x , y ) );
		return maxx;
	}
	int querymark ( int u , int v ) 
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			int tmp = query ( 1 , 1 , n , pos[top[u]] , pos[u] );
			if ( tmp ) return rev[tmp];
			u = fa[top[u]];
		}
		// cout << u << v << endl;
		if ( dep[u] < dep[v] ) swap ( u , v );
		// cout << "st" << endl;
		// cout << v << ' ' << u << endl;
		// cout << pos[v] << ' ' << pos[u] << endl;
		// cout << "ed" << endl;
		return rev[query ( 1 , 1 , n , pos[v] , pos[u] )];
	}
}T;

char ch;
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , m = read();
	for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
	L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 );
	T.upd ( 1 , 1 , n , pos[1] );
	while ( m -- )
	{
		cin >> ch;
		int u = read();
		if ( ch == 'C' ) T.upd ( 1 , 1 , n , pos[u] );
		else cout << T.querymark ( 1 , u ) << endl;
	}
	return 0;
}

P3833 [SHOI2012] 魔法树

很板的题 相当于是树链剖分+区间修改区间查询线段树

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define int long long
const int N = 1e5 + 5;

// char buf[1<<24] , *p1 , *p2;
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , a[N];

vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }

int dep[N] , fa[N] , sz[N] , son[N];
int top[N] , timer , pos[N] , rev[N];

struct LCA 
{
	void dfs1 ( int u , int f )
	{
		dep[u] = dep[fa[u] = f] + 1 , sz[u] = 1;
		for ( auto v : e[u] )
			if ( v ^ f )
			{
				dfs1 ( v , u );
				sz[u] += sz[v];
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}		
	void dfs2 ( int u , int tp )
	{
		top[u] = tp , pos[u] = ++timer , rev[timer] = u;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto v : e[u] ) if ( v ^ fa[u] && v ^ son[u] ) dfs2 ( v , v );
	}
}L;

struct tree
{
	struct node { int sum , add; } t[N<<2];
	inl void up ( int p ) { t[p].sum = t[ls].sum + t[rs].sum; }
	inl void pushadd ( int p , int l , int r , int val ) { t[p].add += val , t[p].sum += ( r - l + 1 ) * val; }
	inl void down ( int p , int l , int r ) { if ( t[p].add ) pushadd ( lson , t[p].add ) , pushadd ( rson , t[p].add ) , t[p].add = 0; }
	void upd ( int p , int l , int r , int x , int y , int val )
	{
		if ( x <= l && r <= y ) return pushadd ( p , l , r , val ) , void();
		down(p,l,r);
		if ( x <= mid ) upd ( lson , x , y , val );
		if ( mid + 1 <= y ) upd ( rson , x , y , val );
		up(p);
	}
	int query ( int p , int l , int r , int x , int y )
	{
		if ( x <= l && r <= y ) return t[p].sum;
		int sum = 0; down(p,l,r);
		if ( x <= mid ) sum += query ( lson , x , y );
		if ( mid + 1 <= y ) sum += query ( rson , x , y );
		return sum;
	}
	void updsum ( int u , int v , int w )
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			upd ( 1 , 1 , n , pos[top[u]] , pos[u] , w );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		upd ( 1 , 1 , n , pos[v] , pos[u] , w );
	}
}T;

char ch;
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read();
	for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() + 1 , v = read() + 1 , add ( u , v ) , add ( v , u );
	L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 );
	m = read();
	for ( int i = 1 , u , v , w ; i <= m ; i ++ )
	{
		cin >> ch;
		if ( ch == 'A' ) u = read() + 1 , v = read() + 1 , w = read() , T.updsum ( u , v , w );
		else u = read() + 1 , cout << T.query ( 1 , 1 , n , pos[u] , pos[u] + sz[u] - 1 ) << endl;
	}
	return 0;
}

P1505 [国家集训队] 旅游

码量 \(max\) 但实际上并不难()

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r>>1)
#define endl '\n'
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
const int N = 2e5 + 5;
const int inf = 0x3f3f3f3f;

// char buf[1<<24] , *p1 , *p2;
// #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , a[N] , u[N] , v[N] , w[N];

vector<pii> e[N];
inl void add ( int u , int v , int w ) { e[u].eb(v,w); }

int dep[N] , fa[N] , sz[N] , son[N];
int top[N] , timer , pos[N] , rev[N];

struct LCA 
{
	void dfs1 ( int u , int f )
	{
		dep[u] = dep[fa[u] = f] + 1 , sz[u] = 1;
		for ( auto [v,w] : e[u] )
			if ( v ^ f )
			{
				dfs1 ( v , u ) , a[v] = w , sz[u] += sz[v];
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}		
	void dfs2 ( int u , int tp )
	{
		top[u] = tp , pos[u] = ++timer , rev[timer] = u;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto [v,w] : e[u] ) if ( v ^ fa[u] && v ^ son[u] ) dfs2 ( v , v );
	}
}L;

struct tree
{
	struct node { int sum , maxx , minn , rev; } t[N<<2];
	inl void up ( int p ) { t[p].sum = t[ls].sum + t[rs].sum , t[p].minn = min ( t[ls].minn , t[rs].minn ) , t[p].maxx = max ( t[ls].maxx , t[rs].maxx ); }
	inl void pushrev ( int p ) { t[p].rev ^= 1 , t[p].sum = -t[p].sum , t[p].maxx = -t[p].maxx , t[p].minn = -t[p].minn , swap ( t[p].maxx , t[p].minn ); }
	inl void down ( int p ) { if ( t[p].rev ) pushrev(ls) , pushrev(rs) , t[p].rev ^= 1; }
	void build ( int p , int l , int r )
	{
		if ( l == r ) return t[p].maxx = t[p].minn = t[p].sum = a[rev[l]] , void();
		build(lson) , build(rson) , up(p);
	}
	void upd ( int p , int l , int r , int x , int val )
	{
		if ( l == r ) return t[p].maxx = t[p].minn = t[p].sum = val , void();
		down(p);
		if ( x <= mid ) upd ( lson , x , val );
		else upd ( rson , x , val );
		up(p);
	}
	
	void updrev ( int p , int l , int r , int x , int y )
	{
		if ( x <= l && r <= y ) return pushrev(p) , void();
		down(p);
		if ( x <= mid ) updrev ( lson , x , y );
		if ( mid + 1 <= y ) updrev ( rson , x , y );
		up(p);
	}
	void urev ( int u , int v )
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			updrev ( 1 , 1 , n , pos[top[u]] , pos[u] );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		updrev ( 1 , 1 , n , pos[v] + 1 , pos[u] );
	}

	int querysum ( int p , int l , int r , int x , int y )
	{
		if ( x <= l && r <= y ) return t[p].sum;
		int sum = 0; down(p);
		if ( x <= mid ) sum += querysum ( lson , x , y );
		if ( mid + 1 <= y ) sum += querysum ( rson , x , y );
		return sum;
	}
	int qsum ( int u , int v )
	{
		int res = 0;
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			res += querysum ( 1 , 1 , n , pos[top[u]] , pos[u] );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		res += querysum ( 1 , 1 , n , pos[v] + 1 , pos[u] );
		return res;
	}

	int querymaxx ( int p , int l , int r , int x , int y )
	{
		if ( x <= l && r <= y ) return t[p].maxx;
		int maxx = -inf; down(p);
		if ( x <= mid ) maxx = max ( maxx , querymaxx ( lson , x , y ) );
		if ( mid + 1 <= y ) maxx = max ( maxx , querymaxx ( rson , x , y ) );
		return maxx;
	}
	int qmaxx ( int u , int v )
	{
		int maxx = -inf;
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			maxx = max ( maxx , querymaxx ( 1 , 1 , n , pos[top[u]] , pos[u] ) );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		maxx = max ( maxx , querymaxx ( 1 , 1 , n , pos[v] + 1 , pos[u] ) );
		return maxx;
	}

	int queryminn ( int p , int l , int r , int x , int y )
	{
		if ( x <= l && r <= y ) return t[p].minn;
		int minn = inf; down(p);
		if ( x <= mid ) minn = min ( minn , queryminn ( lson , x , y ) );
		if ( mid + 1 <= y ) minn = min ( minn , queryminn ( rson , x , y ) );
		return minn;
	}
	int qminn ( int u , int v )
	{
		int minn = inf;
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			minn = min ( minn , queryminn ( 1 , 1 , n , pos[top[u]] , pos[u] ) );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		minn = min ( minn , queryminn ( 1 , 1 , n , pos[v] + 1 , pos[u] ) );
		return minn;
	}

}T;


string s;
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read();
	for ( int i = 1 ; i < n ; i ++ ) u[i] = read() + 1 , v[i] = read() + 1 , w[i] = read() , add ( u[i] , v[i] , w[i] ) , add ( v[i] , u[i] , w[i] );
	L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 );
	T.build ( 1 , 1 , n );
	m = read();
	for ( int i = 1 , x , y ; i <= m ; i ++ )
	{
		cin >> s;
		switch ( s[0] )
		{
			case 'C' : x = read() , y = read() , T.upd ( 1 , 1 , n , pos[max(u[x],v[x])] , y ); break;
			case 'N' : x = read() + 1 , y = read() + 1 , T.urev ( x , y ); break;
			case 'S' : x = read() + 1 , y = read() + 1 , cout << T.qsum ( x , y ) << endl; break;
			case 'M' : x = read() + 1 , y = read() + 1 , cout << ( s[1] == 'A' ? T.qmaxx ( x , y ) : T.qminn ( x , y ) ) << endl; break;
		}
	}
	return 0;
}

P2486 [SDOI2011] 染色

\(upd\ on\ 10.20:\) 代码全篇重写 自己写拍调出来了 非常优美的代码() \(csp\ rp++\)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
const int N = 1e5 + 5;

int read ()
{
	int x = 0 , f = 1;
	char ch = cin.get();
	while ( !isdigit ( ch ) ) { if ( ch == '-' ) f = -1; ch = cin.get(); }
	while ( isdigit ( ch ) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = cin.get(); }
	return x * f;
}

int n , m , a[N];

int sz[N] , fa[N] , dep[N] , son[N];
int pos[N] , rev[N] , top[N] , timer;

vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }
struct LCA
{
	void dfs1 ( int u , int ff )
	{
		sz[u] = 1 , fa[u] = ff , dep[u] = dep[ff] + 1;
		for ( auto v : e[u] )
			if ( v ^ ff )
			{
				dfs1 ( v , u );
				sz[u] += sz[v];
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}
	void dfs2 ( int u , int tp )
	{
		top[u] = tp , pos[u] = ++ timer , rev[timer] = u;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto v : e[u] ) if ( v ^ fa[u] && v ^ son[u] ) dfs2 ( v , v );
	}
}L;

struct Tree
{
	struct node { int lc , rc , sum , cov; node() { lc = rc = sum = cov = 0; } node ( int lc , int rc , int sum , int cov ) { this->lc = lc , this->rc = rc , this->sum = sum , this->cov = cov; } } t[N<<2];
	inl node merge ( const node &a , const node &b )
	{
		if ( !a.sum ) return b;
		if ( !b.sum ) return a;
		node res;
		res.lc = a.lc , res.rc = b.rc;
		res.sum = a.sum + b.sum;
		if ( a.rc == b.lc ) res.sum --;
		return res;
	}
	inl void pushcol ( int p , int val ) { t[p] = (node){ val , val , 1 , val }; }
	inl void down ( int p ) { if ( t[p].cov ) pushcol ( ls , t[p].cov ) , pushcol ( rs , t[p].cov ) , t[p].cov = 0; }
	inl void up ( int p ) { t[p] = merge ( t[ls] , t[rs] ); }
	void build ( int p , int l , int r )
	{
		if ( l == r ) return t[p] = (node){ a[rev[l]] , a[rev[l]] , 1 , 0 } , void();
		build ( lson ) , build ( rson ) , up(p);
	}
	void upd ( int p , int l , int r , int x , int y , int val )
	{
		if ( x <= l && r <= y ) return pushcol(p,val);
		down(p);
		if ( x <= mid ) upd ( lson , x , y , val );
		if ( mid + 1 <= y ) upd ( rson , x , y , val );
		up(p);
	}
	node query ( int p , int l , int r , int x , int y )
	{
		//cout << p << ' ' << l << ' ' << r << ' ' << x << ' ' << y << endl;
		if ( x <= l && r <= y ) return t[p];
		node res; down(p);
		if ( y <= mid ) return query ( lson , x , y );
		else if ( mid + 1 <= x ) return query ( rson , x , y );
		else return merge ( query ( lson , x , y ) , query ( rson , x , y ) );
	}

	void updcol ( int u , int v , int w )
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			upd ( 1 , 1 , n , pos[top[u]] , pos[u] , w );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		upd ( 1 , 1 , n , pos[v] , pos[u] , w );
	}
	
	int querycol ( int u , int v )
	{
		node resu , resv;
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] )
			{
				resv = merge ( query ( 1 , 1 , n , pos[top[v]] , pos[v] ) , resv );
				v = fa[top[v]];
			}
			else
			{
				resu = merge ( query ( 1 , 1 , n , pos[top[u]] , pos[u] ) , resu );
				u = fa[top[u]];
			}
		}
		//cout << "OK" << u << ' ' << v << endl;
		//cout << "OK" << pos[u] << ' ' << pos[v] << endl;
		//cout << resu.sum << ' ' << resu.lc << ' ' << resu.rc << endl;
		//cout << query ( 1 , 1 , n , pos[v] , pos[u] ).sum << endl;
		if ( dep[u] < dep[v] ) resv = merge ( query ( 1 , 1 , n , pos[u] , pos[v] ) , resv );
		else resu = merge ( query ( 1 , 1 , n , pos[v] , pos[u] ) , resu );
		//cout << resu.sum << ' ' << resu.lc << ' ' << resu.rc << endl;
		swap ( resu.lc , resu.rc );
		return merge ( resu , resv ).sum;
	}
}T;

char op;
signed main ()
{
	//freopen ( "gen.in" , "r" , stdin );
	//freopen ( "zhengjie.out" , "w" , stdout );
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , m = read();
	for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
	for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
	L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 ) , T.build ( 1 , 1 , n );
	//for ( int i = 1 ; i <= n ; i ++ ) cout << dep[i] << ' '; cout << endl;
	//for ( int i = 1 ; i <= n ; i ++ ) cout << top[i] << ' '; cout << endl;
	//for ( int i = 1 ; i <= n ; i ++ ) cout << fa[i] << ' '; cout << endl;
	for ( int i = 1 ; i <= m ; i ++ )
	{
		cin >> op;
		int u = read() , v = read() , w;
		if ( op == 'C' ) w = read() , T.updcol ( u , v , w );
		else cout << T.querycol ( u , v ) << endl;
	}
	return 0;
}

P7735 [NOI2021] 轻重边

\(1h\)写完了

请教一下 \(xz\_w\) 发现题没审明白 重构了 \(1h\) 过了样例

卡在 \(45pts\) \(1h\) 最后与 \(bot\) 代码文本比对发现查询挂了() 非常玄妙的题目转化和构造方法()

我们可以将这个题转化为树上查询两点之间同色相邻点对的数目

这样我们对于每一次修改操作 将这段路径上的点赋值为一个从未出现过的权值

这样我们保证了路径上的所有重边都是相邻的同色点对 那么对这个东西进行计数即可

新学习了查询的写法 结构体创造的时候需要使用构造函数

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define fi first
#define se second
#define mkp make_pair
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int N = 1e5 + 5;
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}

int n , m;

vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }

int sz[N] , son[N] , dep[N] , fa[N];
int timer , rev[N] , pos[N] , top[N];

struct LCA
{
	void dfs1 ( int u , int ff )
	{
		dep[u] = dep[ff] + 1 , fa[u] = ff , sz[u] = 1;
		for ( auto v : e[u] )
			if ( v ^ ff )
			{
				dfs1 ( v , u );
				sz[u] += sz[v];
				if ( sz[son[u]] < sz[v] ) son[u] = v;
			}
	}
	void dfs2 ( int u , int tp )
	{
		top[u] = tp , pos[u] = ++timer , rev[timer] = u;
		if ( son[u] ) dfs2 ( son[u] , tp );
		for ( auto v : e[u] ) if ( v != fa[u] && v != son[u] ) dfs2 ( v , v );
	}
}L;

struct Tree
{
	struct node
	{
		int lc , rc , sum , cov;
		node() { lc = rc = sum = cov = 0; }
		node ( int lc , int rc , int sum , int cov ) { this->lc = lc , this->rc = rc , this->sum = sum , this->cov = cov; }
	} t[N<<2];//区间内同色相邻点对个数
	inl void pushcov ( int p , int l , int r , int val ) { t[p].cov = t[p].lc = t[p].rc = val , t[p].sum = r - l; }
	inl void down ( int p , int l , int r ) { if ( t[p].cov ) pushcov ( lson , t[p].cov ) , pushcov ( rson , t[p].cov ) , t[p].cov = 0; }
	inl node merge ( node u , node v ) { node res; res.lc = u.lc , res.rc = v.rc; res.sum = u.sum + v.sum + ( u.rc == v.lc ); return res; }
	inl void up ( int p ) { t[p] = merge ( t[ls] , t[rs] ); }
	void build ( int p , int l , int r )
	{
		if ( l == r ) return t[p] = { -l , -l , 0 , 0 } , void();
		build ( lson ) , build ( rson ) , up(p);
	}
	void upd ( int p , int l , int r , int x , int y , int val )
	{
		if ( x <= l && r <= y ) return pushcov ( p , l , r , val );
		down(p,l,r);
		if ( x <= mid ) upd ( lson , x , y , val );
		if ( mid + 1 <= y ) upd ( rson , x , y , val );
		up(p);
	}
	void updsum ( int u , int v , int w )
	{
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
			upd ( 1 , 1 , n , pos[top[u]] , pos[u] , w );
			u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) swap ( u , v );
		upd ( 1 , 1 , n , pos[v] , pos[u] , w );
	}
	node query ( int p , int l , int r , int x , int y )
	{
		if ( x <= l && r <= y ) return t[p];
		down(p,l,r);
		if ( y <= mid ) return query ( lson , x , y );
		else if ( mid + 1 <= x ) return query ( rson , x , y );
		else return merge ( query ( lson , x , y ) , query ( rson , x , y ) );
	}
	int querysum ( int u , int v )
	{
		node resu , resv;
		while ( top[u] != top[v] )
		{
			if ( dep[top[u]] < dep[top[v]] ) resv = merge ( query ( 1 , 1 , n , pos[top[v]] , pos[v] ) , resv ); v = fa[top[v]];
			else resu = merge ( query ( 1 , 1 , n , pos[top[u]] , pos[u] ) , resu ) , u = fa[top[u]];
		}
		if ( dep[u] < dep[v] ) resv = merge ( query ( 1 , 1 , n , pos[u] , pos[v] ) , resv );
		else resu = merge ( query ( 1 , 1 , n , pos[v] , pos[u] ) , resu );
		swap ( resu.lc , resu.rc );
		return merge ( resu , resv ).sum;
	}
}T;

void init()
{
	timer = 0;
	memset ( son , 0 , sizeof son );
	for ( int i = 1 ; i <= n ; i ++ ) e[i].clear();
	memset ( T.t , 0 , sizeof T.t );
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int TT = read();
	while ( TT -- )
	{
		init();
		n = read() , m = read();
		for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
		L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 ) , T.build ( 1 , 1 , n );
		for ( int i = 1 ; i <= m ; i ++ )
		{
			int op = read() , u = read() , v = read();
			if ( op == 1 ) T.updsum ( u , v , i );
			else cout << T.querysum ( u , v ) << endl;
		}
	}
	return 0;
}
posted @ 2023-08-11 19:58  Echo_Long  阅读(11)  评论(0编辑  收藏  举报