zoukankan      html  css  js  c++  java
  • LightOJ 1348 Aladdin and the Return Journey

    1348 - Aladdin and the Return Journey

    Time Limit: 2 second(s) Memory Limit: 32 MB

    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

    Output for Sample Input

    1

    4

    10 20 30 40

    0 1

    1 2

    1 3

    3

    0 2 3

    1 1 100

    0 2 3

    Case 1:

    90

    170

    Note

    Dataset is huge, use faster I/O methods.


    Problem Setter: Jane Alam Jan
     
     
    这条同样是树链剖分,然后不同的是这条题是点上面有权,不是边上面有权。
    然后再查询的时候注意一下dep[u]==dep[v]的时候不要直接返回,还要query一下
     
     
     
    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    #define root 1,n,1
    #define lr rt<<1
    #define rr rt<<1|1
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    typedef long long LL;
    const int N= 100010;
    int n,q,s;
    int eh[N],et[N<<2],nxt[N<<2],w[N<<2],tot=0;
    int pos,p[N],top[N],rnk[N],dep[N],fa[N],son[N],siz[N];
    
    void init()
    {
        memset(eh,-1,sizeof(eh));
        memset(son,-1,sizeof(son));
        tot=0;
        pos=1;
    }
    
    void addedge(int u,int v){
        et[tot]=v;nxt[tot]=eh[u];eh[u]=tot++;
        et[tot]=u;nxt[tot]=eh[v];eh[v]=tot++;
    }
    
    void dfs1(int u,int father,int d)
    {
        dep[u]=d;
        fa[u]=father;
        siz[u]=1;
        for(int i=eh[u];~i;i=nxt[i]){
            int v=et[i];
            if(v != father){
                dfs1(v,u,d+1);
                siz[u] += siz[v];
                if( son[u]==-1 || siz[v] > siz[son[u]])
                    son[u]=v;
            }
        }
    }
    void dfs2(int u,int tp)
    {
        top[u]=tp;
        p[u]= pos++;
        rnk[ p[u] ]= u;
        if( son[u] == -1 )return ;
        dfs2(son[u], tp );
        for(int i=eh[u]; ~i ;i=nxt[i]){
            int v=et[i];
            if(v != son[u] && v!=fa[u] ){
                dfs2(v,v);
            }
        }
    }
    
    int sum[ N<<2 ];
    
    void Up(int rt)
    {
        sum[rt]=sum[lr]+sum[rr];
    }
    
    void build(int l,int r,int rt)
    {
        if(l == r ){
            sum[rt]=0;
            return ;
        }
        int m=(l+r)>>1;
        build(lson);
        build(rson);
        Up(rt);
    }
    
    void update(int l,int r,int rt,int x,int v)
    {
        if( l == r ){
            sum[rt]=v;
            return ;
        }
        int m=(l+r)>>1;
        if(x<=m)
            update(lson,x,v);
        if(x>m)
            update(rson,x,v);
        Up(rt);
    }
    int query(int l,int r,int rt,int L,int R)
    {
        int res=0;
        if( L<=l && r<=R ){
            return sum[rt];
        }
        int m=(l+r)>>1;
        if(L <= m)
            res += query(lson,L,R);
        if(R > m)
            res += query(rson,L,R);
        return res;
    }
    
    int Q(int u,int v)
    {
        int res=0;
        int f1=top[u],f2=top[v];
        while(f1 != f2){
            if(dep[f1] < dep[f2]){
    
                swap(f1,f2);
                swap(u,v);
            }
            res += query(root,p[f1],p[u]);
            u=fa[f1];
            f1=top[u];
        }
        if(dep[u]>dep[v])swap(u,v);
        res += query(root,p[u],p[v]);
        return res;
    }
    int W[N];
    
    int run()
    {
        int u,v,w;
        int op;
        int _,cas=1;
        scanf("%d",&_);
        while(_--){
            printf("Case %d:
    ",cas++);
            scanf("%d",&n);
            init();
    
            for(int i=1;i<=n;++i){
                scanf("%d",&W[i]);
            }
            for(int i=0;i<n-1;++i){
                scanf("%d%d",&u,&v);
                u++;v++;
                addedge(u,v);
            }
    
            dfs1(1,0,0);
            dfs2( 1,1 );
            build(root);
    
           // for(int i=1;i<=n;++i){cout<<p[i]<<' ';}cout<<endl;
    
            for(int i=1;i<=n;++i)
            {
                update(root,p[i],W[i]);
            }
    
            scanf("%d",&q);
            while(q--)
            {
                scanf("%d",&op);
                if( !op )
                {
                    scanf("%d%d",&u,&v);
                      u++;v++;
                    printf("%d
    ",Q(u,v));
                }
                else {
                    scanf("%d%d",&v,&w);
                    v++;
                    update(root,p[v],w);
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
        #endif
        ios::sync_with_stdio(0);
        return run();
    }
     
    only strive for your goal , can you make your dream come true ?
  • 相关阅读:
    linux 系统运维工具13款
    Django2.0 分页的应用
    jvm优化
    SSH-key 在Windows下如何生成公钥和私钥
    申请Let’s Encrypt免费证书,给自己网站增加https访问
    wordpress上传主题以及安装插件 出现ftp的问题解决方案
    php压缩文件
    linux下 如何切换到root用户
    TP3.2.3框架隐藏Home模块以及index.php入口文件的方法
    PHP打开错误提示和关闭错误提示的方法
  • 原文地址:https://www.cnblogs.com/hlmark/p/3932235.html
Copyright © 2011-2022 走看看