HDU5044--Tree(树链剖分)

来源:互联网 发布:淘宝宝贝编辑教程 编辑:程序博客网 时间:2024/05/22 03:40
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
24 21 22 32 4ADD1 1 4 1ADD2 3 4 24 21 22 31 4ADD1 1 4 5ADD2 3 2 4
 

Sample Output
Case #1:1 1 0 10 2 2Case #2:5 0 0 50 4 0
 
思路:树链剖分。。常规做法要TLE、、、
这里先把链拆成线段,然后线扫描一遍、
                                     #include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>#include <map>#include <set>#include <string>#include <iomanip>#include <cassert>using namespace std;#pragma comment(linker, "/STACK:1024000000,1024000000")#define ff(i, n) for(int i=0;i<(n);i++)#define fff(i, n, m) for(int i=(n);i<=(m);i++)#define dff(i, n, m) for(int i=(n);i>=(m);i--)#define travel(e, u) for(int e = u, v = vv[u]; e; e = nxt[e], v = vv[e])#define bit(n) (1LL<<(n))typedef long long LL;typedef unsigned long long ULL;void work();int main(){//    freopen("in.txt", "r", stdin);//    freopen("out.txt", "w", stdout);    work();}void scanf(int & x, char c = 0){    while((c = getchar()) < '0' || c > '9');    x = c - '0';    while((c = getchar()) >= '0' && c <= '9') x = x * 10 + (c - '0');}/*****************************************华丽分割线**********************************************/#define maxn 200800#define N 100080#define lson id<<1,l,mid#define rson id<<1|1,mid+1,rint first[N],nxt[maxn],vv[maxn];int fa[N],Pos[N],Size[N],Son[N],fPos[N];int dep[N],Top[N];char ope[10];LL Ans1[N],Ans2[N];int e,pos;int firstadd[N],Nxt[10*maxn],Vv[10*maxn];int firstadd2[N],Nxt2[10*maxn],Vv2[10*maxn];int E,E2;void scanf_f(int & a)  {      bool ok = 0;    a = 0;      char c;      while((c = getchar()) < '0' || c > '9')    {        if(c == '-')    ok = 1;    }    a = c - '0';      while((c = getchar()) >= '0' && c <= '9')          a = a*10 + c - '0';      if(ok)    a = -a;}  void init(int n){    e = pos = E = E2 = 0;    memset(first,-1,sizeof(first));    memset(firstadd,-1,sizeof(firstadd));    memset(firstadd2,-1,sizeof(firstadd2));    memset(Son,-1,sizeof(Son));}void addedge(int u,int v){    vv[e] = v;  nxt[e] = first[u];  first[u] = e++;    vv[e] = u;  nxt[e] = first[v];  first[v] = e++;}void AddEdge(int u,int v){    Vv[E] = v;    Nxt[E] = firstadd[u];    firstadd[u] = E++;}void AddEdge2(int u,int v){    Vv2[E2] = v;    Nxt2[E2] = firstadd2[u];    firstadd2[u] = E2++;}void dfs(int u,int pre){    dep[u] = dep[pre] + 1;    Size[u] = 1;    for(int i = first[u];i != -1;i = nxt[i])    {        int v = vv[i];        if(v == pre)    continue;        fa[v] = u;        dfs(v,u);        Size[u] += Size[v];        if(Son[u] == -1 || Size[v] > Size[Son[u]])            Son[u] = v;    }}void dfs2(int u,int t){    Pos[u] = ++pos;    fPos[pos] = u;    Top[u] = t;    if(Son[u] != -1)        dfs2(Son[u],t);    for(int i = first[u];i != -1;i = nxt[i])    {        int v = vv[i];        if(v != fa[u] && v != Son[u])            dfs2(v,v);    }}void gao(int u,int v,int add){    int f1 = Top[u],f2 = Top[v];    while(f1 != f2)    {        if(dep[f1] < dep[f2])        {            swap(u,v);            swap(f1,f2);        }        AddEdge(Pos[f1],add);        AddEdge(Pos[u]+1,-add);        u = fa[f1]; f1 = Top[u];    }    if(dep[u] > dep[v]) swap(u,v);    AddEdge(Pos[u],add);    AddEdge(Pos[v]+1,-add);}void gao1(int u,int v,int add){    int f1 = Top[u],f2 = Top[v];    while(f1 != f2)    {        if(dep[f1] < dep[f2])        {            swap(u,v);            swap(f1,f2);        }        if(f1 == u)        {            AddEdge2(Pos[f1],add);            AddEdge2(Pos[u]+1,-add);        }        else        {            AddEdge2(Pos[f1],add);            AddEdge2(Pos[u]+1,-add);        }        u = fa[f1]; f1 = Top[u];    }    if(dep[u] > dep[v]) swap(u,v);    AddEdge2(Pos[Son[u]],add);    AddEdge2(Pos[v]+1,-add);}struct Edge{    int u,v;}edge[N];void work(){    int t,cas = 0;    scanf("%d",&t);    while(t--)    {        int n,m;        scanf_f(n);        scanf_f(m);        init(n);        for(int i = 1;i < n;i++)        {            int u,v;            scanf_f(u);            scanf_f(v);            addedge(u,v);            edge[i].u = u,edge[i].v = v;        }        dep[1] = 0;        dfs(1,1);        dfs2(1,1);        int u,v,k;        for(int i = 1;i <= m;i++)        {            scanf("%s",ope);            if(ope[3] == '1')            {                                scanf_f(u);                scanf_f(v);                scanf_f(k);                gao(u,v,k);            }            else            {                                scanf_f(u);                scanf_f(v);                scanf_f(k);                gao1(u,v,k);            }        }        printf("Case #%d:\n",++cas);        LL ans1 = 0,ans2 = 0;        for(int i = 1;i <= n;i++)        {            for(int j = firstadd[i];j != -1;j = Nxt[j])                ans1 += Vv[j];            for(int j = firstadd2[i];j != -1;j = Nxt2[j])                ans2 += Vv2[j];            Ans1[fPos[i]] = ans1;            Ans2[fPos[i]] = ans2;        }        for(int i = 1;i <= n;i++)        {            printf("%I64d",Ans1[i]);            if(i == n)    puts("");            else printf(" ");        }        for(int i= 1;i < n;i++)        {            u = edge[i].u,v = edge[i].v;            if(dep[u] > dep[v])    swap(u,v);            printf("%I64d",Ans2[v]);            if(i != n-1)                printf(" ");        }        puts("");    }}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                


0 0