Description
Input
Output
Sample Input
Sample Input
Sample Output
84
131
27
84
131
27
84
HINT
Source
树上带修莫队
树上莫队?用类似于括号序列的东西搞到序列上
注意分类讨论x和y互为祖先的情况
带修莫队?维护3个东西,l,r,t(时间戳)
三关键字排序
第一关键字l,第二关键字r,这两个按块来排
第三关键字t,在同一块中递增
如果我们把块的size搞成n^(2/3)
复杂度就是n^(5/3)
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200010;
inline int read()
{
int sc = 0; char ch = getchar();
while( ch < '0' || ch > '9' ) ch = getchar();
while( ch >= '0' && ch <= '9' ) sc = sc * 10 + ch - '0', ch = getchar();
return sc;
}
int f[MAXN], g[MAXN], id[MAXN], tim, n, m, Q, sz;
int head[MAXN], cnt, last[MAXN], dep[MAXN], fa[MAXN][19];
int v[MAXN], w[MAXN], block, bl[MAXN], cnt1, cnt2, col[MAXN], appear[MAXN];
bool vis[MAXN];
long long ans[MAXN], cur;
struct query
{
int l, r, t, id;
bool operator < ( const query &b ) const { return ( bl[ l ] < bl[ b.l ] ) || ( bl[ l ] == bl[ b.l ] && bl[ r ] < bl[ b.r ] ) || ( bl[ l ] == bl[ b.l ] && bl[ r ] == bl[ b.r ] && t < b.t ); }
}a[MAXN], b[MAXN];
struct edge { int to, nxt; }e[MAXN];
inline void add(int x, int y) { e[ ++cnt ] = { y, head[ x ] }; head[ x ] = cnt; }
inline void addedge(int x, int y) { add( x, y ); add( y, x ); }
inline void dfs(int x)
{
id[ f[ x ] = ++tim ] = x;
for( int i = head[ x ] ; i ; i = e[ i ].nxt )
if( e[ i ].to ^ fa[ x ][ 0 ] )
fa[ e[ i ].to ][ 0 ] = x, dep[ e[ i ].to ] = dep[ x ] + 1, dfs( e[ i ].to );
id[ g[ x ] = ++tim ] = x;
}
inline void init()
{
for( int j = 1 ; j <= 18 ; j++ )
for( int i = 1 ; i <= n ; i++ )
fa[ i ][ j ] = fa[ fa[ i ][ j - 1 ] ][ j - 1 ];
}
inline void pushup(int &x, int d)
{
for( int i = 18 ; i >= 0 ; i-- )
if( d >= ( 1 << i ) ) d -= 1 << i, x = fa[ x ][ i ];
}
inline int lca(int x, int y)
{
if( dep[ x ] < dep[ y ] ) swap( x, y );
if( dep[ x ] ^ dep[ y ] ) pushup( x, dep[ x ] - dep[ y ] );
if( x == y ) return x;
for( int i = 18 ; i >= 0 ; i-- )
if( fa[ x ][ i ] ^ fa[ y ][ i ] ) x = fa[ x ][ i ], y = fa[ y ][ i ];
return fa[ x ][ 0 ];
}
inline void add(int x)
{
if( vis[ x ] ) cur -= 1ll * v[ col[ x ] ] * w[ appear[ col[ x ] ]-- ];
else cur += 1ll * v[ col[ x ] ] * w[ ++appear[ col[ x ] ] ];
vis[ x ] ^= 1;
}
inline void modify(int x, int c) { if( vis[ x ] ) { add( x ); col[ x ] = c; add( x ); } else col[ x ] = c; }
int main()
{
n = read(); m = read(); Q = read();
for( int i = 1 ; i <= m ; i++ ) v[ i ] = read();
for( int i = 1 ; i <= n ; i++ ) w[ i ] = read();
for( int i = 1 ; i < n ; i++ ) addedge( read(), read() );
for( int i = 1 ; i <= n ; i++ ) last[ i ] = col[ i ] = read();
dfs( 1 ); init(); sz = pow( tim, 2.0 / 3 );
for( int i = 1 ; i <= tim ; i++ ) bl[ i ] = ( i - 1 ) / sz;
while( Q-- )
{
int opt = read(), x = read(), y = read();
if( opt )
{
if( f[ x ] > f[ y ] ) swap( x, y );
a[ ++cnt1 ] = { lca( x, y ) == x ? f[ x ] : g[ x ], f[ y ], cnt2, cnt1 };
}
else b[ ++cnt2 ].l = x, b[ cnt2 ].r = last[ x ], last[ x ] = b[ cnt2 ].t = y;
}
sort( a + 1, a + cnt1 + 1 );
int L = 1, R = 0, T = 1;
for( int i = 1 ; i <= cnt1 ; i++ )
{
while( T <= a[ i ].t ) modify( b[ T ].l, b[ T ].t ), T++;
while( T > a[ i ].t ) modify( b[ T ].l, b[ T ].r ), T--;
while( L > a[ i ].l ) add( id[ --L ] );
while( L < a[ i ].l ) add( id[ L++ ] );
while( R > a[ i ].r ) add( id[ R-- ] );
while( R < a[ i ].r ) add( id[ ++R ] );
//printf( "%d %d %d %d\n", a[ i ].l, a[ i ].r, a[ i ].t, a[ i ].id );
int x = id[ L ], y = id[ R ], LCA = lca( x, y );
if( x != LCA && y != LCA ) { add( LCA ); ans[ a[ i ].id ] = cur; add( LCA ); }
else ans[ a[ i ].id ] = cur;
}
for( int i = 1 ; i <= cnt1 ; i++ ) printf( "%lld\n", ans[ i ] );
}