poj 2763 Housewife Wind(树链剖分,边权)

来源:互联网 发布:谁用过网络麻将开挂 编辑:程序博客网 时间:2024/06/04 18:04

题目链接
题意:给出一颗树,初始在s点,有2个操作0操作,表示求s到u路径和
1操作表示把第i条边权重变为w。

树链剖分,然后用线段树维护就可以了

//#include<bits/stdc++.h>#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<stack>#include<cstring>#include<set>#include<map>#include<string>#include<cassert>using namespace std;#define cl(a,b) memset(a,b,sizeof(a))#define fastIO ios::sync_with_stdio(false);cin.tie(0);#define ll  long long#define pb push_back#define gcd __gcd#define For(i,j,k) for(int i=(j);i<=k;i++)#define lowbit(i) (i&(-i))#define _(x) printf("%d\n",x)typedef vector<ll> vec;typedef pair<int,int> PI;const double EPS = 1e-8;const int maxn = 2e5+100;const int inf  = 1 << 28;int n,q,s;int e[maxn][3];struct Edge{    int to,next;}es[maxn<<2];int head[maxn],tot;int top[maxn];int p[maxn];int fa[maxn];int fp[maxn];int num[maxn];int deep[maxn];int son[maxn];int pos;void addEdge(int u,int v){    es[tot].to=v;es[tot].next=head[u];head[u]=tot++;}void init(){    tot=0;    cl(head,-1);    pos=0;    cl(son,-1);}void dfs(int u,int pre,int d){    deep[u]=d;    fa[u]=pre;    num[u]=1;    for(int i=head[u];~i;i=es[i].next){        int v=es[i].to;        if(v!=pre){            dfs(v,u,d+1);            num[u]+=num[v];            if(son[u]==-1||num[son[u]]<num[v])son[u]=v;        }    }}void getpos(int u,int sp){    top[u]=sp;    p[u]=pos++;    fp[p[u]]=u;    if(son[u]==-1)return ;    getpos(son[u],sp);    for(int i=head[u];~i;i=es[i].next){        int v=es[i].to;        if(v!=fa[u]&&v!=son[u])getpos(v,v);    }}//int sum[maxn<<2];void pushUp(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int rt,int l,int r){    if(l==r){        sum[rt]=e[fp[l]][2];        return ;    }    int mid=l+r>>1;    build(rt<<1,l,mid);    build(rt<<1|1,mid+1,r);    pushUp(rt);}void update(int rt,int l,int r,int i,int v){    if(l==i&&r==i){        sum[rt]=v;        return ;    }    int mid=l+r>>1;    if(i<=mid)update(rt<<1,l,mid,i,v);    else update(rt<<1|1,mid+1,r,i,v);    pushUp(rt);}int query(int rt,int l,int r,int x,int y){    if(x<=l&&r<=y){        return sum[rt];    }    int mid=l+r>>1;    int ans=0;    if(x<=mid)ans+=query(rt<<1,l,mid,x,y);    if(y>mid)ans+=query(rt<<1|1,mid+1,r,x,y);    return ans;}int findSum(int u,int v){    int f1=top[u],f2=top[v];    int ans=0;    while(f1!=f2){        if(deep[f1]<deep[f2]){            swap(f1,f2);            swap(v,u);        }        ans+=query(1,0,pos-1,p[f1],p[u]);        u=fa[f1];f1=top[u];    }    if(u==v)return ans;    if(deep[u]>deep[v])swap(u,v);    ans+=query(1,0,pos-1,p[son[u]],p[v]);    return ans;}int main(){    while(~scanf("%d%d%d",&n,&q,&s)){        init();        for(int i=1;i<n;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]);        }        dfs(1,0,0);        getpos(1,1);        //build(1,0,pos-1);        for(int i=1;i<n;i++){            if(deep[e[i][0]]<deep[e[i][1]])swap(e[i][0],e[i][1]);            update(1,0,pos-1,p[e[i][0]],e[i][2]);        }        while(q--){            int t;scanf("%d",&t);            if(t){                int i,v;                scanf("%d%d",&i,&v);                if(deep[e[i][0]]<deep[e[i][1]])swap(e[i][0],e[i][1]);                update(1,0,pos-1,p[e[i][0]],v);            }            else {                int u;scanf("%d",&u);                printf("%d\n",findSum(s,u));                s=u;            }        }    }    return 0;}
0 0
原创粉丝点击