zoukankan      html  css  js  c++  java
  • HDU 5044 Tree 树链剖分+区间标记

    Tree

    Problem Description
    You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N

    There are N - 1 edges numbered from 1 to N - 1.

    Each node has a value and each edge has a value. The initial value is 0.

    There are two kind of operation as follows:

    ● ADD1 u v k: for nodes on the path from u to v, the value of these nodes increase by k.

    ● ADD2 u v k: for edges on the path from u to v, the value of these edges increase by k.

    After finished M operation on the tree, please output the value of each node and edge.
     
    Input
    The first line of the input is T (1 ≤ T ≤ 20), which stands for the number of test cases you need to solve.

    The first line of each case contains two integers N ,M (1 ≤ N, M ≤105),denoting the number of nodes and operations, respectively.

    The next N - 1 lines, each lines contains two integers u, v(1 ≤ u, v ≤ N ), denote there is an edge between u,v and its initial value is 0.

    For the next M line, contain instructions “ADD1 u v k” or “ADD2 u v k”. (1 ≤ u, v ≤ N, -105 ≤ k ≤ 105)
     
    Output
    For each test case, print a line “Case #t:”(without quotes, t means the index of the test case) at the beginning.

    The second line contains N integer which means the value of each node.

    The third line contains N - 1 integer which means the value of each edge according to the input order.
     
    Sample Input
    2 4 2 1 2 2 3 2 4 ADD1 1 4 1 ADD2 3 4 2 4 2 1 2 2 3 1 4 ADD1 1 4 5 ADD2 3 2 4
     
    Sample Output
    Case #1: 1 1 0 1 0 2 2 Case #2: 5 0 0 5 0 4 0
     

    题意:

      给你一棵树,n个结点

      1、将u到v之间的结点权值加k;

      2、将u到v之间的边权加k。

      输出经过修改后所有的边权和点权。

    题解:

      这题线段树超时

      需要用到一个区间更新小技巧

      比如x,y这个区间+k,那么sum[x] += k, sum[y+1] -= k;

      最后统计一个前缀和就可以了

      这题读入挂超时,不用能A,格式也要注意了

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 2e5+10, M = 1e3+20, mod = 1e9+7, inf = 2e9;
    
    int dep[N],head[N],t=1,sz[N],fa[N],indexS,top[N],pos[N],son[N],idpos[N];
    struct ss{int to,next,id;}e[N*2];
    int n;
    void add(int u,int v,int id)
    {e[t].to = v;e[t].next = head[u];e[t].id=id;head[u] = t++;}
    void dfs(int u) {
        int k = 0;
        sz[u] = 1;
        dep[u] = dep[fa[u]] + 1;
        for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            if(to == fa[u]) continue;
            fa[to] = u;
            idpos[to] = e[i].id;
            dfs(to);
            sz[u] += sz[to];
            if(sz[to] > sz[k]) k = to;
        }
        if(k) son[u] = k;
    }
    void dfs(int u,int chain) {
        int k = 0;
        pos[u] = ++indexS;
        top[u] = chain;
        if(son[u] > 0)
            dfs(son[u],chain);
        for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            if(dep[to] > dep[u] && son[u] != to)
                dfs(to,to);
        }
    }
    LL sum[N],sum2[N];
    void updateL(int x,int y,int k) {
        while(top[x] != top[y]) {
            if(dep[top[x]] < dep[top[y]]) swap(x,y);
            sum2[pos[top[x]]] +=k;
            sum2[pos[x]+1] -=k;
            x = fa[top[x]];
        }
        if(dep[x] < dep[y]) swap(x,y);
        sum2[pos[y]] +=k;
        sum2[pos[x]+1] -=k;
    }
    void updateW(int x,int y,int k) {
        while(top[x] != top[y]) {
            if(dep[top[x]] < dep[top[y]]) swap(x,y);
            sum[pos[top[x]]] += k;
            sum[pos[x] + 1] -= k;
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x,y);
        sum[pos[x] + 1] += k;
        sum[pos[y] + 1] -= k;
    }
    void init() {
        t = 1;
        memset(head,0,sizeof(head));
        indexS = 0;fa[1] = 0;
        for(int i = 0; i <= n+5; ++i) sum[i] = 0, sum2[i] = 0;
        for(int i = 0; i <= n; ++i) son[i] = 0,sz[i] = 0;
    }
    int T,m,cas = 1;
    LL f[N];
    int main() {
        scanf("%d",&T);
        while(T--) {
          scanf("%d%d",&n,&m);
            init();
            for(int i = 1 ; i < n; ++i) {
                int x,y;
                scanf("%d%d",&x,&y);
                add(x,y,i),add(y,x,i);
            }
            dfs(1);
            dfs(1,1);
            while(m--) {
                char ch[10];
                int x,y,k;
                scanf("%s",ch);
               scanf("%d%d%d",&x,&y,&k);
                if(ch[3] == '1') {
                    updateL(x,y,k);
                }
                else if(x!=y){
                    updateW(x,y,k);
                }
            }
            printf("Case #%d:
    ",cas++);
            for(int i = 2; i <= n; ++i)
                sum[i]+=sum[i-1],sum2[i]+=sum2[i-1];
            for(int i = 2; i <= n; ++i) f[idpos[i]] = sum[pos[i]];
            for(int i = 1; i < n; ++i)
                printf("%I64d ",sum2[pos[i]]);
            printf("%I64d
    ",sum2[pos[n]]);
            for(int i = 1; i < n-1; ++i) printf("%I64d ",f[i]);
            if(n-1 > 0)printf("%I64d",f[n-1]);
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    Win7升Windows10有获取通知,但是就不推送的解决方法
    使用git@osc管理现有项目
    暗黑符文之语1.10
    springcloud干活之服务消费者(feign)
    springcloud干货之服务消费者(ribbon)
    springcloud干货之服务注册与发现(Eureka)
    java对redis的基本操作
    微信公众号开发模式中文乱码
    Java 验证代理ip
    maven将项目及第三方jar打成一个jar包
  • 原文地址:https://www.cnblogs.com/zxhl/p/6705957.html
Copyright © 2011-2022 走看看