图论之树链剖分模板

来源:互联网 发布:sql注入 预处理 编辑:程序博客网 时间:2024/06/05 03:00
#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;#define MEM(a,b) memset(a,b,sizeof(a));int n,m,s;const int maxn=100010;struct Node{    int u,v,w,next;}e[maxn],edge[2*maxn];int cnt;int head[maxn];//记siz[v]表示以v为根的子树的节点数,dep[v]表示v的深度(根深度为1),top[v]表示v所在的链的//顶端节点,fa[v]表示v的父亲,son[v]表示与v在同一重链上的v的儿子节点(姑且称为重儿子),//id[v]表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位置。int dep[maxn],siz[maxn],son[maxn],fa[maxn];int top[maxn],id[maxn];////top 最近的重链父节点int num;void addedge(int u,int v){    edge[cnt].u=u;edge[cnt].v=v;edge[cnt].next=head[u]++;head[u]=cnt++;}void dfs1(int u,int f,int d){    dep[u]=d;    siz[u]=1;    son[u]=0;    fa[u]=f;    for(int i=head[u];i!=-1;i=edge[i].next){        int v=edge[i].v;        if(v==f)continue;        dfs1(v,u,d+1);        siz[u]+=siz[v];        if(siz[son[u]]<siz[v])            son[u]=v;    }}void dfs2(int u,int tp){    top[u]=tp;    id[u]=++num;    if(son[u])dfs2(son[u],tp);    for(int i=head[u];i!=-1;i=edge[i].next){        int v=edge[i].v;        if(v==fa[u]||v==son[u])continue;        dfs2(v,v);    }}struct Tree{    int l,r,val;}tree[4*maxn];#define lson 2*o,l,mid#define rson 2*o+1,mid+1,rint Val[maxn];void pushup(int x){    tree[x].val=tree[2*x].val+tree[2*x+1].val;}void build(int o,int l,int r){//建树一致    tree[o].l=l;tree[o].r=r;    if(l==r){        tree[o].val=Val[l];        return;    }    int mid=(l+r)>>1;    build(lson);    build(rson);    pushup(o);}void update(int o,int a,int b){//更新操作一致    if(tree[o].l==tree[o].r){        tree[o].val=b;        return;    }    int mid=(tree[o].l+tree[o].r)>>1;    if(a<=mid)        update(2*o,a,b);    else        update(2*o+1,a,b);    pushup(o);}int query(int o,int l,int r){    if(tree[o].l>=l&&tree[o].r<=r){        return tree[o].val;    }    int mid=(tree[o].l+tree[o].r)>>1;    if(r<=mid)        return query(2*o,l,r);    else if(l>mid)        return query(2*o+1,l,r);    else        return query(lson)+query(rson);}int find(int u,int v){    int tp1=top[u],tp2=top[v];    int ans=0;    while(tp1!=tp2){        if(dep[tp1]<dep[tp2]){            swap(tp1,tp2);            swap(u,v);        }        ans+=query(1,id[tp1],id[u]);        u=fa[tp1];        tp1=top[u];    }    if(u==v)return ans;    if(dep[u]>dep[v])swap(u,v);    ans+=query(1,id[son[u]],id[v]);    return ans;}int main(){    scanf("%d%d%d",&n,&m,&s);    cnt=0;num=0;    MEM(head,-1);    for(int i=1;i<n;i++){        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);        addedge(e[i].u,e[i].v);        addedge(e[i].v,e[i].u);    }    dfs1(1,0,1);    dfs2(1,1);    for(int i=1;i<n;i++){        if(dep[e[i].u]<dep[e[i].v])            std::swap(e[i].u,e[i].v);        Val[id[e[i].u]]=e[i].w;    }    build(1,1,num);    for(int i=0;i<m;i++){        int ok,x,y;        scanf("%d",&ok);        if(ok==0){            scanf("%d",&x);            printf("%d\n",find(s,x));            s=x;        }        else{            scanf("%d%d",&x,&y);            update(1,id[e[x].u],y);        }    }    return 0;}

0 0