hdu5044 Tree(树链剖分+差分)

来源:互联网 发布:英语课文朗读软件 编辑:程序博客网 时间:2024/05/22 00:25

线段树会T,要用O(n)的区间修改+单点查询,也就是像差值似的,把区间修改变成点修改,最后前缀和就是每个点的值。(可是我这样还是差点T掉了o(╥﹏╥)o)

#include <cstdio>#include <algorithm>#include <cstring>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define N 100010inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int n,m,p[N],h[N],num,dep[N],fa[N],son[N],size[N],top[N],id[N],dfn;ll ans1[N],ans2[N];struct edge{    int to,next,val;}data[N<<1];void dfs1(int x){    size[x]=1;    for(int i=h[x];i;i=data[i].next){        int y=data[i].to;        if(fa[x]==y) continue;        fa[y]=x;dep[y]=dep[x]+1;p[i>>1]=y;        dfs1(y);size[x]+=size[y];        if(size[y]>size[son[x]]) son[x]=y;    }}void dfs2(int x,int tp){    id[x]=++dfn;top[x]=tp;    if(son[x]) dfs2(son[x],tp);    for(int i=h[x];i;i=data[i].next){        int y=data[i].to;        if(y==fa[x]||y==son[x]) continue;dfs2(y,y);    }}void doadd1(int x,int y,int val){    while(top[x]!=top[y]){        if(dep[top[x]]<dep[top[y]]) swap(x,y);        ans1[id[top[x]]]+=val,ans1[id[x]+1]-=val;        x=fa[top[x]];    }    if(id[x]>id[y]) swap(x,y);    ans1[id[x]]+=val;ans1[id[y]+1]-=val;}void doadd2(int x,int y,int val){    while(top[x]!=top[y]){        if(dep[top[x]]<dep[top[y]]) swap(x,y);        ans2[id[top[x]]]+=val,ans2[id[x]+1]-=val;        x=fa[top[x]];    }    if(id[x]>id[y]) swap(x,y);if(id[x]==id[y]) return;    ans2[id[x]+1]+=val;ans2[id[y]+1]-=val;}int main(){//  freopen("a.in","r",stdin);    int t=read();    for(int tt=1;tt<=t;++tt){        printf("Case #%d:\n",tt);n=read();m=read();        memset(h,0,sizeof(h));memset(fa,0,sizeof(fa));        memset(son,0,sizeof(son));dfn=0;num=1;        memset(ans1,0,sizeof(ans1));memset(ans2,0,sizeof(ans2));        for(int i=1;i<n;++i){            int x=read(),y=read();            data[++num].to=y;data[num].next=h[x];h[x]=num;            data[++num].to=x;data[num].next=h[y];h[y]=num;        }        dep[1]=1;dfs1(1);dfs2(1,1);        while(m--){            char op[6];scanf("%s",op);int x=read(),y=read(),z=read();            if(op[3]=='1') doadd1(x,y,z);            else doadd2(x,y,z);        }        for(int i=1;i<=n;++i){ans1[i]+=ans1[i-1];ans2[i]+=ans2[i-1];}        for(int i=1;i<=n;++i){            if(i==n) printf("%lld\n",ans1[id[i]]);            else printf("%lld ",ans1[id[i]]);        }        for(int i=1;i<n;++i){            if(i==n-1) printf("%lld\n",ans2[id[p[i]]]);            else printf("%lld ",ans2[id[p[i]]]);        }        if(n==1) puts("");    }    return 0;}