hdu 5044(树链剖分+区间标记小优化)

来源:互联网 发布:50而知天命什么意思 编辑:程序博客网 时间:2024/06/08 10:30
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, -10 5 ≤ k ≤ 10 5)
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
题意:一颗n个结点的树,两种操作: 1、将u到v之间的结点权值加k;2、将u到v之间的边权加k。输出经过修改后所有的边权和点权。
点剖和边剖,第一次做边剖,边剖对于点剖的区别
#include <bits/stdc++.h>using namespace std;#pragma comment(linker, "/STACK:1024000000,1024000000")const int maxn=100000+110;#define lowbit(x) (x)&(-x)typedef long long ll;template <class T>bool scan_d(T &ret){    char c;     int sgn;     T bit = 0.1;    if (c=getchar(), c==EOF)     {        return 0;    }    while (c!= '-' && c != '.' && (c < '0' || c > '9'))     {        c = getchar();    }    sgn = (c == '-') ? -1 : 1;    ret = (c == '-') ? 0 : (c - '0');    while (c = getchar(), c >= '0' && c <= '9')    {        ret = ret * 10 + (c - '0');    }    if (c == ' ' || c == '\n')    {        ret *= sgn;        return 1;    }    while (c = getchar(), c >= '0' && c <= '9')    {        ret += (c - '0') * bit, bit /= 10;    }    ret *= sgn;    return 1;}template <class T>inline void print_d(T x){    if (x > 9)    {        print_d(x/10);    }    putchar(x % 10 + '0');}struct sad{    int to,next,id;}G[maxn<<2];int h[maxn],si;void add(int u,int v,int id){    G[si].to=v;    G[si].id=id;    G[si].next=h[u];    h[u]=si++;}int siz[maxn],dep[maxn];int fa[maxn],son[maxn],top[maxn];int fid[maxn],pos;int p[maxn],fp[maxn];ll sum[maxn],sum1[maxn];void dfs1(int u,int f,int d){    fa[u]=f;    dep[u]=d;    siz[u]=1;    son[u]=-1;    for(int i=h[u];~i;i=G[i].next)    {        int v=G[i].to;        if(v^f)        {            fid[G[i].id]=v;            dfs1(v,u,d+1);            siz[u]+=siz[v];            if(son[u]==-1||siz[son[u]]<siz[v])                son[u]=v;        }    }}void dfs2(int u,int sf){    top[u]=sf;    p[u]=pos++;    fp[p[u]]=u;    if(son[u]==-1) return;    dfs2(son[u],sf);    for(int i=h[u];~i;i=G[i].next)    {        int v=G[i].to;        if(son[u]!=v&&fa[u]!=v)            dfs2(v,v);    }}void init(){    memset(h,-1,sizeof(h));    si=0;    pos=1;}void Change1(int u,int v,int val){    int f1=top[u],f2=top[v];    while(f1!=f2){        if(dep[f1]<dep[f2])        {            swap(f1,f2);            swap(u,v);        }        sum[p[f1]]+=val;        sum[p[u]+1]-=val;        u=fa[f1];        f1=top[u];    }    if(dep[u]>dep[v]) swap(u,v);    sum[p[u]]+=val;    sum[p[v]+1]-=val;}void Change2(int u,int v,int val){    int f1=top[u],f2=top[v];    while(f1!=f2){        if(dep[f1]<dep[f2])        {            swap(f1,f2);            swap(u,v);        }        sum1[p[f1]]+=val;        sum1[p[u]+1]-=val;        u=fa[f1];        f1=top[u];    }    if(u==v) return ;//边剖,相等的时候退出    if(dep[u]>dep[v]) swap(u,v);    sum1[p[son[u]]]+=val;//边剖最后更新的是公共祖先和儿子    sum1[p[v]+1]-=val;}int main(){    int hh,n,q;    scanf("%d",&hh);    for(int cas=1;cas<=hh;cas++)    {    scanf("%d%d",&n,&q);        int a,b;         for(int i=1;i<=n+5;i++)        sum[i]=0,sum1[i]=0;        init();        for(int i=1;i<=n-1;i++)        {        scanf("%d%d",&a,&b);            add(a,b,i);            add(b,a,i);        }        dfs1(1,0,1);        dfs2(1,0);        while(q--)        {            char op[10];            int a,b,val;            scanf(" %s",op);            scanf("%d%d%d",&a,&b,&val);            if(op[3]=='1')                Change1(a,b,val);            else if(a!=b) Change2(a,b,val);        }        printf("Case #%d:\n",cas );        for(int i=1;i<=n;i++)            sum[i]+=sum[i-1],sum1[i]+=sum1[i-1];        printf("%I64d",sum[p[1]] );        for(int i=2;i<=n;i++)        {            printf(" %I64d",sum[p[i]]);        }        printf("\n");        for(int i=1;i<n;i++)        {            if(i!=1)                printf(" ");            printf("%I64d",sum1[p[fid[i]]]);//边剖是把边的权值加载边的结束点        }        printf("\n");    }}


阅读全文
0 0
原创粉丝点击