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

    Aladdin and the Return Journey

    Time Limit: 2000ms
    Memory Limit: 32768KB
    This problem will be judged on LightOJ. Original ID: 1348
    64-bit integer IO format: %lld      Java class name: Main

    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

    Output for Sample Input

    Case 1:

    90

    170

    解题:树链剖分

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 30010;
     4 struct arc {
     5     int to,next;
     6     arc(int x = 0,int y = -1) {
     7         to = x;
     8         next = y;
     9     }
    10 } e[maxn<<1];
    11 int head[maxn],fa[maxn],top[maxn],dep[maxn];
    12 int siz[maxn],son[maxn],loc[maxn],clk,tot;
    13 int c[maxn];
    14 void add(int u,int v) {
    15     e[tot] = arc(v,head[u]);
    16     head[u] = tot++;
    17 }
    18 void update(int i,int val) {
    19     while(i <= clk) {
    20         c[i] += val;
    21 
    22         i += i&-i;
    23     }
    24 }
    25 int sum(int i,int ret = 0) {
    26     while(i > 0) {
    27         ret += c[i];
    28         i -= i&-i;
    29         //cout<<ret<<"++++"<<endl;
    30     }
    31     return ret;
    32 }
    33 void FindHeavyEdge(int u,int father,int depth) {
    34     fa[u] = father;
    35     dep[u] = depth;
    36     siz[u] = 1;
    37     son[u] = -1;
    38     for(int i = head[u]; ~i; i = e[i].next) {
    39         if(e[i].to == father) continue;
    40         FindHeavyEdge(e[i].to,u,depth + 1);
    41         siz[u] += siz[e[i].to];
    42         if(son[u] == -1 || siz[e[i].to] > siz[son[u]])
    43             son[u] = e[i].to;
    44     }
    45 }
    46 void ConnectHeavyEdge(int u,int ancestor) {
    47     top[u] = ancestor;
    48     loc[u] = ++clk;
    49     if(son[u] != -1) ConnectHeavyEdge(son[u],ancestor);
    50     for(int i = head[u]; ~i; i = e[i].next) {
    51         if(e[i].to == fa[u] || son[u] == e[i].to) continue;
    52         ConnectHeavyEdge(e[i].to,e[i].to);
    53     }
    54 }
    55 int solve(int u,int v,int ret = 0) {
    56     while(top[u] != top[v]) {
    57         if(dep[top[u]] < dep[top[v]]) swap(u,v);
    58         ret += sum(loc[u]) - sum(loc[top[u]]-1);
    59         u = fa[top[u]];
    60     }
    61     if(dep[u] > dep[v]) swap(u,v);
    62     ret += sum(loc[v]) - sum(loc[u]-1);
    63     return ret;
    64 }
    65 int val[maxn];
    66 int main() {
    67     int kase,n,m,u,v,op,cs = 1;
    68     scanf("%d",&kase);
    69     while(kase--) {
    70         scanf("%d",&n);
    71         for(int i = 1; i <= n; ++i) scanf("%d",val + i);
    72         clk = tot = 0;
    73         memset(head,-1,sizeof head);
    74         for(int i = 1; i < n; ++i) {
    75             scanf("%d%d",&u,&v);
    76             add(u+1,v+1);
    77             add(v+1,u+1);
    78         }
    79         FindHeavyEdge(1,0,0);
    80         ConnectHeavyEdge(1,1);
    81         memset(c,0,sizeof c);
    82         for(int i = 1; i <= n; ++i)
    83             update(loc[i],val[i]);
    84         scanf("%d",&m);
    85         printf("Case %d:
    ",cs++);
    86         while(m--) {
    87             scanf("%d%d%d",&op,&u,&v);
    88             if(op) {
    89                 int tmp = sum(loc[u+1]) - sum(loc[u+1]-1);
    90                 update(loc[u+1],-tmp + v);
    91             } else printf("%d
    ",solve(u+1,v+1));
    92         }
    93     }
    94     return 0;
    95 }
    View Code
  • 相关阅读:
    水煮栗子
    张至顺道长羽化登仙+说修行(道经每日清修)
    治疗口腔溃疡的穴位按摩方法
    一年四季的时令蔬菜水果表
    坐式养生八段锦口诀及练法图解
    SOA建设规划
    生鲜电商业务流程规划
    产品定义到产品推广的思路
    生鲜财务核算
    税率与存货、供应商关系
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4845746.html
Copyright © 2011-2022 走看看