码迷,mamicode.com
首页 > 其他好文 > 详细

Lightoj 1348 Aladdin and the Return Journey (树链剖分)(线段树单点修改区间求和)

时间:2017-01-31 18:32:58      阅读:244      评论:0      收藏:0      [点我收藏+]

标签:rar   typedef   magic   indicator   pre   scan   clu   str   ++   

Finally the Great Magical Lamp was in Aladdin‘s hand. Now he wanted to return home. But he didn‘t want to take any help from the Genie because he thought that it might be another adventure for him. All he remembered was the paths he had taken to reach there. But since he took the lamp, all the genies in the cave became angry and they were planning to attack. As Aladdin was not afraid, he wondered how many genies were there. He summoned the Genie from the lamp and asked this.

Now you are given a similar problem. For simplicity assume that, you are given a tree (a connected graph with no cycles) with n nodes, nodes represent places, edges represent roads. In each node, initially there are an arbitrary number of genies. But the numbers of genies change in time. So, you are given a tree, the number of genies in each node and several queries of two types. They are:

1)      0 i j, it means that you have to find the total number of genies in the nodes that occur in path from node i to j (0 ≤ i, j < n).

2)      1 i v, it means that number of genies in node i is changed to v (0 ≤ i < n, 0 ≤ v ≤ 1000).


Input

Input starts with an integer T (≤ 10), denoting the number of test cases.

Each case starts with a blank line. Next line contains an integer n (2 ≤ n ≤ 30000). The next line contains n space separated integers between 0 and 1000, denoting the number of genies in the nodes respectively. Then there are n-1 lines each containing two integers: u v (0 ≤ u, v < n, u ≠ v) meaning that there is an edge from node u and v. Assume that the edges form a valid tree. Next line contains an integer q (1 ≤ q ≤ 105) followed by q lines each containing a query as described above.

Output

For each case, print the case number in a single line. Then for each query 0 i j, print the total number of genies in the nodes that occur in path i to j.

Sample Input

1

 

4

10 20 30 40

0 1

1 2

1 3

3

0 2 3

1 1 100

0 2 3

Sample Output

Case 1:

90

170

技术分享
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define lson(x) ((x<<1))
#define rson(x) ((x<<1)+1)
using namespace std;
typedef long long ll;
const int N=2e5+50;
const int M=N*N+10;
int dep[N],siz[N],fa[N],id[N],son[N],val[N],top[N],c[N]; //top 最近的重链父节点
int num,n,m;
vector<int> v[N];
struct tree {
    int x,y;
    void read() {
        scanf("%d%d",&x,&y);
    }
};
tree e[N];
void dfs1(int u, int f, int d) {
    dep[u] = d;
    siz[u] = 1;
    son[u] = 0;
    fa[u] = f;
    for (int i = 0; i < v[u].size(); i++) {
        int ff = v[u][i];
        if (ff == f) continue;
        dfs1(ff, u, d + 1);
        siz[u] += siz[ff];
        if (siz[son[u]] < siz[ff])
            son[u] = ff;
    }
}
void dfs2(int u, int tp) {
    top[u] = tp;
    id[u] = ++num;
    if (son[u]) dfs2(son[u], tp);
    for (int i = 0; i < v[u].size(); i++) {
        int ff = v[u][i];
        if (ff == fa[u] || ff == son[u]) continue;
        dfs2(ff, ff);
    }
}

struct Tree {
    int l,r,val,sum;
};
Tree tree[4*N];
void pushup(int x) {
    tree[x].val = max(tree[lson(x)].val, tree[rson(x)].val);
    tree[x].sum=tree[lson(x)].sum+tree[rson(x)].sum;
}

void build(int l,int r,int v) {
    tree[v].l=l;
    tree[v].r=r;
    if(l==r) {
        tree[v].val = val[l];
        tree[v].sum=val[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,v*2);
    build(mid+1,r,v*2+1);
    pushup(v);
}
void update(int o,int v,int val) { //log(n)
    if(tree[o].l==tree[o].r) {
        tree[o].val =tree[o].sum= val;
        return ;
    }
    int mid = (tree[o].l+tree[o].r)/2;
    if(v<=mid)
        update(o*2,v,val);
    else
        update(o*2+1,v,val);
    pushup(o);
}
int querySum(int x,int l,int r) {
    if (tree[x].l >= l && tree[x].r <= r) {
        return tree[x].sum;
    }
    int mid = (tree[x].l + tree[x].r) / 2;
    int ans = 0;
    if (l <= mid) ans += querySum(lson(x),l,r);
    if (r > mid) ans += querySum(rson(x),l,r);
    return ans;
}
int Qsum(int u,int v) {
    int tp1 = top[u], tp2 = top[v];
    int ans = 0;
    while (tp1 != tp2) {
        if (dep[tp1] < dep[tp2]) {
            swap(tp1, tp2);
            swap(u, v);
        }
        ans +=querySum(1,id[tp1], id[u]);
        //printf("ans:   %d\n",ans);
        u = fa[tp1];
        tp1 = top[u];
    }
    //if (u == v) return ans;
    if (dep[u] > dep[v]) swap(u, v);
    ans +=querySum(1,id[u], id[v]);
    return ans;
}
void init(){
    for(int i=0;i<N;i++)v[i].clear();
    met(tree,0);met(son,0);met(val,0);
}
int main() {
    int t,T=0;
    scanf("%d",&t);
    while(t--) {
        init();
        ++T;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)scanf("%d",&c[i]);
        for(int i=1; i<n; i++) {
            e[i].read();
            e[i].x++;e[i].y++;
            v[e[i].x].push_back(e[i].y);
            v[e[i].y].push_back(e[i].x);
        }

        num = 0;
        dfs1(1,0,1);
        dfs2(1,1);
        for (int i = 1; i <=n; i++) {
            val[id[i]] = c[i];
        }
        build(1,num,1);
        char s[200];
        scanf("%d",&m);
        printf("Case %d:\n",T);
        while(m--) {
            int o,x,y;
            scanf("%d",&o);
            scanf("%d%d",&x,&y);
            if (o)
                x++,update(1,id[x],y);
            else
                x++,y++,printf("%d\n",Qsum(x,y));
        }
    }
    return 0;
}
View Code

 

Lightoj 1348 Aladdin and the Return Journey (树链剖分)(线段树单点修改区间求和)

标签:rar   typedef   magic   indicator   pre   scan   clu   str   ++   

原文地址:http://www.cnblogs.com/jianrenfang/p/6358952.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!