FZU 2082 过路费 (树链剖分)

来源:互联网 发布:优畅网络正规吗 编辑:程序博客网 时间:2024/04/30 20:14

传送门:http://acm.fzu.edu.cn/problem.php?pid=2082
这题有个注意点,就是他更改的时候是更改第a条边,那我们怎么才能知道第a条边是更改线段树上的哪个点呢?因为我们在表示边的时候是用一个点表示他的父亲边,所以第a条边是用这条边上深度大的那个点来表示的,problem solved。
一次AC!

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <iostream>#include <vector>#include <map>#include <set>#include <queue>#include <ctime>using namespace std;typedef long long ll;typedef pair<int,int> pii;#define pb push_back#define mp make_pair#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define calm (l+r)>>1const int INF=2139062143;const int maxn=50010;struct EE{    int to,next,val;    EE(){}    EE(int t,int n,int v):to(t),next(n),val(v){}}edge[maxn<<1];struct EEE{    int from,to,val;    EEE(){}    EEE(int f,int t,int v):from(f),to(t),val(v){}}Edge[maxn];int n,m,Ecnt,tot,head[maxn];int top[maxn],fa[maxn],id[maxn],son[maxn],num[maxn],rev[maxn],deep[maxn];int val[maxn];inline void add(int a,int b,int c){    edge[Ecnt]=EE(b,head[a],c);    head[a]=Ecnt++;}void dfs(int s,int pre,int d){    fa[s]=pre;deep[s]=d;num[s]=1;son[s]=0;    for(int i=head[s];~i;i=edge[i].next){        int t=edge[i].to;        if(t==pre)continue;        dfs(t,s,d+1);num[s]+=num[t];        if(son[s]==0||num[son[s]]<num[t]){            son[s]=t;        }    }}void dfs(int s,int rt){    top[s]=rt;id[s]=++tot;rev[tot]=s;    if(!son[s])return;    dfs(son[s],rt);    for(int i=head[s];~i;i=edge[i].next){        int t=edge[i].to;        if(t==fa[s]||t==son[s])continue;        dfs(t,t);    }}int sum[maxn<<2];inline void pushup(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){    sum[rt]=0;    if(l==r){        sum[rt]=val[rev[l]];        return;    }    int m=calm;    build(lson);build(rson);    pushup(rt);}void update(int x,int v,int l,int r,int rt){    if(l==r){sum[rt]=v;return;}    int m=calm;    if(x<=m)update(x,v,lson);    else update(x,v,rson);    pushup(rt);}ll query(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R){        return sum[rt];    }    int m=calm;    ll ans=0;    if(L<=m)ans+=query(L,R,lson);    if(R>m)ans+=query(L,R,rson);    return ans;}int getID(int x){    EEE e=Edge[x];    if(deep[e.from]>deep[e.to])return e.from;    return e.to;}ll solve(int x,int y){    int f1=top[x],f2=top[y];    ll ans=0;    while(f1!=f2){        if(deep[f1]<deep[f2]){            swap(f1,f2);swap(x,y);        }        ans+=query(id[f1],id[x],1,tot,1);        x=fa[f1];f1=top[x];    }    if(x!=y){        if(deep[x]>deep[y])swap(x,y);        ans+=query(id[son[x]],id[y],1,tot,1);    }    return ans;}int main(){    //freopen("D://input.txt","r",stdin);    while(scanf("%d%d",&n,&m)!=EOF){        Ecnt=0;memset(head,-1,sizeof head);        for(int i=1;i<n;i++){            scanf("%d%d%d",&Edge[i].from,&Edge[i].to,&Edge[i].val);            add(Edge[i].from,Edge[i].to,Edge[i].val);            add(Edge[i].to,Edge[i].from,Edge[i].val);        }        tot=0;        dfs(1,0,1);dfs(1,1);        for(int i=1;i<n;i++){            int a=Edge[i].from;            int b=Edge[i].to;            if(deep[a]>deep[b]){                val[a]=Edge[i].val;            }            else{                val[b]=Edge[i].val;            }        }        build(1,tot,1);        while(m--){            int op,a,b;scanf("%d%d%d",&op,&a,&b);            if(op==0){                int x=getID(a);                update(id[x],b,1,tot,1);                val[x]=b;            }            else{                printf("%I64d\n",solve(a,b));            }        }    }    return 0;}
0 0
原创粉丝点击