fzu2028

//Accepted    7324 KB    203 ms
/*
    source:fzu2028
    time  :2015.5.29
    by    :songt
  */
/*题解:
树链剖分
单点更新,求路径和
  */
#include <cstdio>
#include <cstring>

const int imax_n = 50005;

int max(int a,int b)
{
    return a>b?a:b;
}

void swap(int &a,int &b)
{
    int t=a;
    a=b;
    b=t;
}

struct Edge
{
    int u,v;
    Edge(){}
    Edge(int u,int v):u(u),v(v){}
}
edge[2*imax_n];
int head[imax_n];
int next[2*imax_n];
int tot;
void addEdge(int u,int v)
{
    edge[tot]=Edge(u,v);
    next[tot]=head[u];
    head[u]=tot++;
}
int fa[imax_n],deep[imax_n],num[imax_n],son[imax_n];
int p[imax_n],fp[imax_n],top[imax_n];
int pos;
void init()
{
    memset(head,-1,sizeof(head));
    memset(next,-1,sizeof(next));
    tot=0;
    memset(son,-1,sizeof(son));
    pos=0;
}
void dfs1(int u,int pre,int depth)
{
    deep[u]=depth;
    fa[u]=pre;
    num[u]=1;
    for (int i=head[u];i+1;i=next[i])
    {
        int v=edge[i].v;
        if (v!=pre)
        {
            dfs1(v,u,depth+1);
            num[u]+=num[v];
            if (son[u]==-1 || num[son[u]]<num[v])
                son[u]=v;
        }
    }
}

void dfs2(int u,int sp)
{
    p[u]=pos++;
    fp[p[u]]=u;
    top[u]=sp;
    if (son[u]==-1) return ;
    dfs2(son[u],sp);
    for (int i=head[u];i+1;i=next[i])
    {
        int v=edge[i].v;
        if (v!=fa[u] && v!=son[u])
        {
            dfs2(v,v);
        }
    }
}
struct Tree
{
    int l,r;
    long long sum;
    int tmax;
}f[imax_n*3];
void build(int t,int l,int r)
{
    f[t].l=l;
    f[t].r=r;
    f[t].sum=0;
    f[t].tmax=0;
    if (l==r)
    {
        return ;
    }
    int mid=(f[t].l+f[t].r)>>1;
    build(2*t,l,mid);
    build(2*t+1,mid+1,r);
}
void update(int t,int k,int value)
{
    if (f[t].l==k && f[t].r==k)
    {
        f[t].sum=value;
        f[t].tmax=value;
        return ;
    }
    int mid=(f[t].l+f[t].r)>>1;
    if (k<=mid) update(2*t,k,value);
    else update(2*t+1,k,value);
    f[t].sum=f[2*t].sum+f[2*t+1].sum;
    f[t].tmax=max(f[2*t].tmax,f[2*t+1].tmax);
}
long long query(int t,int l,int r,int &tmax)
{
    if (f[t].l==l && f[t].r==r)
    {
        tmax=f[t].tmax;
        return f[t].sum;
    }
    int mid=(f[t].l+f[t].r)>>1;
    if (r<=mid) return query(2*t,l,r,tmax);
    else
    {
        if (l>mid) return query(2*t+1,l,r,tmax);
        else
        {
            int tmax1,tmax2;
            long long sum1,sum2;
            sum1=query(2*t,l,mid,tmax1);
            sum2=query(2*t+1,mid+1,r,tmax2);
            tmax=max(tmax1,tmax2);
            return sum1+sum2;
        }
    }
}

long long find(int u,int v,int tmax)
{
    int f1=top[u],f2=top[v];
    long long sum=0;
    int tmp=0;
    int t;
    while (f1!=f2)
    {
        if (deep[f1]<deep[f2])
        {
            swap(f1,f2);
            swap(u,v);
        }
        sum+=query(1,p[f1],p[u],t);
        tmp=max(tmp,t);
        u=fa[f1];
        f1=top[u];
    }
    if (u==v) return sum;
    if (deep[u]>deep[v]) swap(u,v);
    sum+=query(1,p[son[u]],p[v],t);
    tmp=max(tmp,t);
    tmax=tmp;
    return sum;
}

int e[imax_n][3];
int n,m;

int main()
{
    while (scanf("%d%d",&n,&m)==2)
    {
        init();
        for (int i=0;i<n-1;i++)
        {
            scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
            addEdge(e[i][0],e[i][1]);
            addEdge(e[i][1],e[i][0]);
        }
        dfs1(1,0,0);
        dfs2(1,1);
        //printf("after dfs\n");
        build(1,0,pos-1);
        //printf("after build\n");
        for (int i=0;i<n-1;i++)
        {
            if (deep[e[i][0]]<deep[e[i][1]])
                swap(e[i][0],e[i][1]);
            update(1,p[e[i][0]],e[i][2]);
        }
        //printf("after insert\n");
        int kind;
        int u,v,c;
        int tmax;
        for (int i=0;i<m;i++)
        {
            scanf("%d%d%d",&kind,&u,&v);
            if (kind==0)
            {
                update(1,p[e[u-1][0]],v);
            }
            else
            {
                printf("%lld\n",find(u,v,tmax));
            }
        }
    }
    return 0;
}

时间: 2024-10-29 19:09:05

fzu2028的相关文章