FZU 2082 过路费(树链剖分)

来源:互联网 发布:河大教务网络管理系统 编辑:程序博客网 时间:2024/05/01 00:59

很基础的树链剖分练习+树状数组


#include<cstring>#include<string>#include<iostream>#include<queue>#include<cstdio>#include<algorithm>#include<map>#include<cstdlib>#include<cmath>#include<vector>//#pragma comment(linker, "/STACK:1024000000,1024000000");using namespace std;#define INF 0x3f3f3f3f#define maxn 100005int x[maxn],y[maxn];int fir[maxn],nex[maxn],v[maxn],w[maxn],e_max;int son[maxn],fa[maxn],siz[maxn],deep[maxn],top[maxn],pos[maxn],tot;int val[maxn];long long c[maxn+10];void init_(){    c[0]=c[1]=0;    memset(fir,-1,sizeof fir);    memset(son,-1,sizeof son);    memset(siz,0,sizeof siz);    memset(c,0,sizeof c);    e_max=0;    tot=1;}void add_edge(int s,int t,int c){    int e=e_max++;    v[e]=t;    w[e]=c;    nex[e]=fir[s];    fir[s]=e;}int lowbit(int x){    return x&-x;}void update(int x,int val){    for(; x<=maxn; x+=lowbit(x)) c[x]+=val;}long long query(int x){    if(x==0) return 0;    long long sum=0;    for(; x>0; x-=lowbit(x)) sum+=c[x];    return sum;}void dfs1(int k,int pre,int d){    deep[k]=d;    siz[k]++;    fa[k]=pre;    for(int i=fir[k]; ~i; i=nex[i])    {        int e=v[i];        if(e!=pre)        {            val[e]=w[i];            dfs1(e,k,d+1);            siz[k]+=siz[e];            if(son[k]==-1||siz[son[k]]<siz[e]) son[k]=e;        }    }}void dfs2(int k,int sp){    top[k]=sp;    pos[k]=tot++;    update(pos[k],val[k]);    if(son[k]==-1) return ;    dfs2(son[k],sp);    for(int i=fir[k]; ~i; i=nex[i])    {        int e=v[i];        if(e!=son[k]&&e!=fa[k])        {            dfs2(e,e);        }    }}void Query(int s,int t){    long long ans=0;    int f1=top[s],f2=top[t];    while(f1!=f2)    {        if(deep[f1]<deep[f2]) swap(f1,f2),swap(s,t);        ans+=query(pos[s])-query(pos[f1]-1);        s=fa[f1];        f1=top[s];    }    if(s==t)    {        printf("%I64d\n",ans);        return ;    }    if(deep[s]>deep[t]) swap(s,t);    ans+=query(pos[t])-query(pos[s]);    printf("%I64d\n",ans);}int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=EOF)    {        init_();        for(int i=1; i<n; i++)        {            int c;            scanf("%d%d%d",&x[i],&y[i],&c);            add_edge(x[i],y[i],c);            add_edge(y[i],x[i],c);        }        dfs1(1,-1,1);        dfs2(1,1);        while(m--)        {            int op;            scanf("%d",&op);            if(op==0)            {                int i,ti;                scanf("%d%d",&i,&ti);                if(deep[x[i]]<deep[y[i]]) swap(x[i],y[i]);                i=x[i];                update(pos[i],-(query(pos[i])-query(pos[i]-1)));                update(pos[i],ti);            }            else            {                int l,r;                scanf("%d%d",&l,&r);                Query(l,r);            }        }    }    return 0;}


0 0