Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- #define mx 20005
- #define inf 1000000000000000000
- #define int long long
- #define piii pair <int, pair <int, int> >
- #define pii pair <int, int>
- #define f first
- #define s second
- #define mp make_pair
- #define lc ((n)<<1)
- #define rc ((n)<<1|1)
- const int N = 3e4+4 , LG = 20;
- int n;
- int P[N][20], lev[N], ch = 0;
- int chainNo[N], head[N], subsize[N], child[N], pos[N];
- int Ar[N], tot = 0 , value[N];
- vector<int> G[N];
- int seg[N*4];
- void build(int n,int b,int e){
- if(b==e) {
- seg[n] = Ar[b];return;
- }
- int mid= (b+e)/2;
- build(lc,b,mid);
- build(rc, mid+1,e);
- seg[n] = seg[lc] + seg[rc];
- }
- void update(int n,int b,int e,int pos,int v){
- if(b==e && b== pos) {
- seg[n] = v;
- return ;
- }
- int mid = (b+e)/2;
- if(pos <= mid ) update(lc,b,mid,pos,v);
- else update(rc,mid+1,e,pos,v);
- seg[n] = seg[lc] + seg[rc];
- }
- int query(int n,int b,int e,int i,int j){
- if(b>j||e<i) return 0;
- if(b>=i && e <= j ) {
- return seg[n];
- }
- int mid = (b+e)/2;
- return query(lc,b,mid,i,j) + query(rc,mid+1,e,i,j);
- }
- void dfs(int u,int p){
- subsize[u] = 1;
- for(int i = 0; i < G[u].size(); i ++ ) {
- int v = G[u][i];
- if(v == p ) continue;
- lev[v] = 1 + lev[u];
- P[v][0] = u; // Modify
- dfs(v,u);
- subsize[u] += subsize[v];
- if(child[u] == -1 || subsize[v] > subsize[child[u]] ) {
- child[u] = v;
- }
- }
- }
- void HLD(int u,int p){
- if(head[ch] == -1) head[ch] = u;
- Ar[ ++tot ] = value[u];
- pos[u] = tot;
- chainNo[u] = ch;
- if(child[u] > 0 ) HLD(child[u], u );
- for(int i = 0; i < G[u].size(); i ++ ) {
- int v = G[u][i];
- if(v == p || v == child[u]) continue;
- ++ch;
- HLD(v,u);
- }
- }
- int LCA(int u,int v){
- if(lev[u] > lev[v]) swap(u,v);
- int d = lev[v] - lev[u];
- for(int i = LG - 1; i >= 0 ; i -- ) {
- if( d &1<<i){
- v = P[v][i];
- }
- }
- if(u==v) return u;
- for(int i = LG-1; i >= 0 ; i -- ) {
- if(P[u][i] != P[v][i]) {
- u = P[u][i];
- v = P[v][i];
- }
- }
- return P[v][0];
- }
- int queryUp(int from, int to){ // Climb up to
- int ret = 0;
- while(chainNo[from ] != chainNo[to] ) {
- int h = head[chainNo[from]];
- ret += query(1,1,tot, pos[h], pos[from]); // Modify
- from = P[h][0];
- }
- ret += query(1,1,tot,pos[to], pos[from]); // Modify
- return ret;
- }
- void process(){
- memset(P,-1,sizeof(P));
- memset(head,-1,sizeof(head));
- memset(child,-1,sizeof(child));
- tot = 0 , ch = 0;
- dfs(1,-1);
- HLD(1,-1);
- build(1,1,tot);
- for(int i = 1; i < LG; i ++ ) {
- for(int j = 1; j <= n; j ++ ) if(P[j][i-1] !=-1 ) P[j][i] = P[P[j][i-1]][i-1];
- }
- }
- int32_t main(){
- //freopen("in.txt", "r", stdin);
- int m, k, p, cas, d, t;
- scanf("%lld", &t);
- cas = 1;
- while(t--){
- scanf("%lld", &n);
- for(int i=1;i<=n;i++){
- scanf("%lld", &value[i]);
- }
- for(int i=1;i<=n-1;i++){
- int a, b;
- scanf("%lld%lld", &a, &b);
- a++;
- b++;
- G[a].push_back(b);
- G[b].push_back(a);
- }
- scanf("%lld", &p);
- process();
- printf("Case %lld:\n", cas++);
- while(p--){
- int a, b;
- scanf("%lld%lld%lld", &m, &a, &b);
- a++;
- if(m){
- value[a] = b;
- update(1, 1, n, pos[a], b);
- }
- else{
- b++;
- k = LCA(a, b);
- printf("%lld\n", queryUp(a, k)+queryUp(b, k)-value[k]);
- }
- }
- for(int i=0;i<=n;i++) G[i].clear();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement