//#define _GLIBCXX_DEBUG #include using namespace std; #define endl '\n' #define lfs cout<= (ll)(n); i--) using ll = long long; using ld = long double; const ll MOD1 = 1e9+7; const ll MOD9 = 998244353; const ll INF = 1e18; using P = pair; templatebool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;} templatebool chmax(T1 &a,T2 b){if(avoid ans(bool x,T1 y,T2 z){if(x)cout<void debug(vector>&v,ll h,ll w){for(ll i=0;i&v,ll h,ll w){for(ll i=0;ivoid debug(vector&v,ll n){if(n!=0)cout<vector>vec(ll x, ll y, T w){vector>v(x,vector(y,w));return v;} ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;} vectordx={1,-1,0,0,1,1,-1,-1};vectordy={0,0,1,-1,1,-1,1,-1}; templatevector make_v(size_t a,T b){return vector(a,b);} templateauto make_v(size_t a,Ts... ts){return vector(a,make_v(ts...));} templateostream &operator<<(ostream &os, const pair&p){return os << p.first << " " << p.second;} templateostream &operator<<(ostream &os, const vector &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;} //mt19937 mt(chrono::steady_clock::now().time_since_epoch().count()); template< typename Monoid, typename OperatorMonoid,typename F, typename G, typename H> struct LazySegmentTree { ll sz, height, n; vector< Monoid > data; vector< OperatorMonoid > lazy; const F f; const G g; const H h; Monoid M1; OperatorMonoid OM0; LazySegmentTree(ll n, const F &f,const G &g, const H &h, Monoid M1, OperatorMonoid OM0):n(n),f(f),g(g),h(h),M1(M1),OM0(OM0){ sz = 1; height = 0; while(sz < n) sz <<= 1, height++; data.assign(2 * sz, M1); lazy.assign(2 * sz, OM0); } void set(ll k, const Monoid &x) { data[k + sz] = x; } void build() { for(ll k = sz - 1; k > 0; k--) { data[k] = f(data[2 * k + 0], data[2 * k + 1]); } } inline void propagate(ll k) { if(lazy[k] != OM0) { lazy[2 * k + 0] = h(lazy[2 * k + 0], lazy[k]); lazy[2 * k + 1] = h(lazy[2 * k + 1], lazy[k]); data[k] = reflect(k); lazy[k] = OM0; } } inline Monoid reflect(ll k) { return lazy[k] == OM0 ? data[k] : g(data[k], lazy[k]); } inline void recalc(ll k) { while(k >>= 1) data[k] = f(reflect(2 * k + 0), reflect(2 * k + 1)); } inline void thrust(ll k) { for(ll i = height; i > 0; i--) propagate(k >> i); } void update(ll a, ll b, const OperatorMonoid &x) { if(a>=b)return; thrust(a += sz); thrust(b += sz - 1); for(ll l = a, r = b + 1; l < r; l >>= 1, r >>= 1) { if(l & 1) lazy[l] = h(lazy[l], x), ++l; if(r & 1) --r, lazy[r] = h(lazy[r], x); } recalc(a); recalc(b); } Monoid query(ll a, ll b) { thrust(a += sz); thrust(b += sz - 1); Monoid L = M1, R = M1; for(ll l = a, r = b + 1; l < r; l >>= 1, r >>= 1) { if(l & 1) L = f(L, reflect(l++)); if(r & 1) R = f(reflect(--r), R); } return f(L, R); } Monoid operator[](const ll &k) { return query(k, k + 1); } template< typename C > ll find_subtree(ll a, const C &check, Monoid &M, bool type) { while(a < sz) { propagate(a); Monoid nxt = type ? f(reflect(2 * a + type), M) : f(M, reflect(2 * a + type)); if(check(nxt)) a = 2 * a + type; else M = nxt, a = 2 * a + 1 - type; } return a - sz; } template< typename C > ll find_first(ll a, const C &check) { Monoid L = M1; if(a <= 0) { if(check(f(L, reflect(1)))) return find_subtree(1, check, L, false); return -1; } thrust(a + sz); ll b = sz; for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) { if(a & 1) { Monoid nxt = f(L, reflect(a)); if(check(nxt)) return find_subtree(a, check, L, false); L = nxt; ++a; } } return -1; } template< typename C > ll find_last(ll b, const C &check) { Monoid R = M1; if(b >= sz) { if(check(f(reflect(1), R))) return find_subtree(1, check, R, true); return -1; } thrust(b + sz - 1); ll a = sz; for(b += sz; a < b; a >>= 1, b >>= 1) { if(b & 1) { Monoid nxt = f(reflect(--b), R); if(check(nxt)) return find_subtree(b, check, R, true); R = nxt; } } return -1; } void print(){ for(ll i=0;isz;//部分木サイズ vectorpar,head; vector>g;//隣接リスト vectoredges;//データ構造に乗せるedge列 vectorin,out;//[in,out)で部分木、[ina,inb]でa~bのパス(aが上) //inは頂点のindexを表す。また、edge列の下側の頂点である HLD(vector>&G,ll r = -1) :g(G),n(G.size()),root(r){ par.assign(n,-1),in.assign(n,-1); out.assign(n,-1),head.assign(n,-1),sz.assign(n,-1); edges.assign(n,edge()); dfs_build(); } void dfs_build(){ if(root == -1){//根がどこでも良い場合(森でも可) for(ll i=0;i sz[g[k][0].to])swap(e, g[k][0]); } } void dfs_hld(ll k){ in[k] = cnt++; for(auto e:g[k]){ if(e.to == par[k])continue; head[e.to] = (e.to == g[k][0].to ? head[k]: e.to); edges[cnt] = e; dfs_hld(e.to); } out[k] = cnt; } ll lca(ll p,ll q){ while(1){ if(in[p] < in[q])swap(p,q); if(head[p] == head[q])return q; p = par[head[p]]; } } vector>query_path(ll p,ll q,bool isEdge=true){ ll r=lca(p,q); vector>ret; for(ll i=0;i<2;i++){ if(i == 1)swap(p,q); while(1){ if(isEdge&&p==r)break; if(head[p]==head[r]){ ret.emplace_back(in[r]+(isEdge?1:i),in[p]+1); break; } ret.emplace_back(in[head[p]],in[p]+1); p = par[head[p]]; } } return ret; } vector>>query_order_path(ll p,ll q,bool isEdge=true){ //非可換クエリ用、配列0を順番を反転したデータ構造に、配列1を通常のデータ構造に vector>>ret(2); ll r=lca(p,q); for(ll i=0;i<2;i++){ if(i == 1)swap(p,q); while(1){ if(isEdge&&p==r)break; if(head[p]==head[r]){ if(i==0) ret[i].emplace_back(n-(in[p]+1),n-(in[r]+(isEdge?1:i))); else ret[i].emplace_back(in[r]+(isEdge?1:i),in[p]+1); break; } if(i==0) ret[i].emplace_back(n-(in[p]+1),n-(in[head[p]])); else ret[i].emplace_back(in[head[p]],in[p]+1); p = par[head[p]]; } } reverse(ret[1].begin(), ret[1].end()); return ret; } pairquery_subtree(ll p,bool isEdge=true){ return make_pair(in[p]+isEdge,out[p]); } }; int main(){ cin.tie(nullptr); ios_base::sync_with_stdio(false); ll res=0,buf=0; bool judge = true; auto f=[&](P x,P y){ return MP(x.fi+y.fi,x.se+y.se); }; auto g=[&](P x,ll y){ return MP(x.fi+x.se*y,x.se); }; auto h=[&](ll x,ll y){ return x+y; }; ll n,k,q;cin>>n>>k>>q; LazySegmentTreeseg(n,f,g,h,MP(0,0),0); vectorc(k); rep(i,0,k){ cin>>c[i];c[i]--; } vector>gg(n); rep(i,0,n-1){ ll u,v;cin>>u>>v;u--;v--; gg[u].EB(v); gg[v].EB(u); } HLD hld(gg,0); vectordep(n); { auto dfs=[&](auto &&f,ll k,ll d,ll par)->void{ dep[k]=d; for(auto e:gg[k]){ if(e.to==par)continue; f(f,e.to,d+1,k); } }; dfs(dfs,0,0,-1); } rep(i,0,n)seg.set(i,P(k,1)); seg.build(); auto ope=[&](ll pos,ll add){ auto p=hld.query_path(0,pos,false); for(auto z:p){ seg.update(z.fi,z.se,-add*2); } seg.update(hld.in[0],hld.in[0]+1,add*(dep[pos]+1)); }; //debug(hld.in,n); //debug(dep,n); //seg.print(); rep(i,0,k){ ope(c[i],1); //seg.print(); } while(q--){ ll type;cin>>type; if(type==1){ ll p,d;cin>>p>>d;p--;d--; ope(c[p],-1); c[p]=d; ope(c[p],1); } else{ ll e;cin>>e;e--; auto p=hld.query_path(0,e,false); ll ret=0; for(auto z:p)ret+=seg.query(z.fi,z.se).fi; cout<