pku2763 Housewife Wind

题意:给定一棵有n( n < 100001 )个结点的带边权的树,处理以下一共q(q < 100001)个操作:

1,改变树的一条边的权;

2,求给定点和某点的距离,后者是编号为1的结点,若是第一次执行操作2,否则为上次执行操作2的给定点。

没有了操作1,这题就是典型的LCA,于是怎样有效地执行操作1就是这题的关键。还记得LCA到RMQ的转化吗点我,过程中DFS会生成一条回路,并且产生一个从遍历次序到结点编号的满射,我们称它为order[]。我们知道,若以结点到根的距离作为树的深度,如果一条边的权增加了delta,那么这条边链接的子树内的所有结点的深度都增加了delta。又因为子树内的结点的遍历次序是连续的,所以我们可以建立从 遍历次序 到 到根的距离的映射dist[],于是每次执行操作1只需对dist[]的一片连续区域作修改即可,可以用线段树或者树状数组。

搞定了操作1,我们发现操作2也被搞出来了,因为LCA(u,v)=order[RMQ(dist[出现u的任意遍历序号...出现v的任意遍历序号])],可能这是出题者的意图吧。

 

 

#include <iostream>
#include 
<vector>
#include 
<cmath>
using namespace std;

#define MAXN 200005
#define LOG 20
typedef pair
<int,int> PAIR;


int order[MAXN],ecnt,dist[MAXN],first[MAXN],last[MAXN],n,q,st,p[MAXN],maxorder,c[MAXN],mn[MAXN][LOG],b[MAXN];
//first[u]表示u首次出现的遍历序号,last[u]表示u最后出现的遍历序号
bool visited[MAXN];

struct Edge{
    
int v,weight,next;
}edg[MAXN];


void init(){
    ecnt
=0;
    memset(p,
-1,sizeof(p));
    memset(dist,
0,sizeof(dist));
    maxorder
=1;
    memset(visited,
false,sizeof(visited));
    memset(c,
0,sizeof(c));
}


void dfs(int pre,int u,int w){
    
int i,v,ordertmp;
    
    visited[u]
=true;
    last[u]
=first[u]=maxorder;
    order[maxorder]
=u;
    dist[maxorder]
=dist[last[pre]]+w;
    ordertmp
=maxorder++;

    
for(i=p[u];i!=-1;i=edg[i].next){
        v
=edg[i].v;
        
if(!visited[v]){
            
            dfs(u,v,edg[i].weight);
            order[maxorder]
=u;
            last[u]
=maxorder;
            dist[maxorder]
=dist[ordertmp];
            maxorder
++;
        }
    }
}

//////////////////////////////////////////////////////////////////////////
//树状数组
inline int lowbit(int x){
    
return x&(-x);
}


int down(int x){
    
int i,res=0;
    
for(i=x;i>0;i-=lowbit(i))
        res
+=c[i];
    
return res;
}

void up(int x,int t){
    
int i;
    
for(i=x;i<maxorder;i+=lowbit(i))
        c[i]
+=t;
}

void build(){
    
int i;
    
for(i=1;i<maxorder;i++)
        b[i]
=dist[i]-dist[i-1];
    
for(i=1;i<maxorder;i++){
        up(i,b[i]);
    }
}

//////////////////////////////////////////////////////////////////////////
//spares table
void preprocess(){
    
int i,j;
    
for(i=1;i<maxorder;i++)
        mn[i][
0]=i;
    
for(j=1;(1<<j)<=maxorder;j++){
        
for(i=1;i+(1<<j)-1<maxorder;i++){
            
if(dist[mn[i][j-1]]<=dist[mn[i+(1<<(j-1))][j-1]])
                mn[i][j]
=mn[i][j-1];
            
else
                mn[i][j]
=mn[i+(1<<(j-1))][j-1];

        }
    }
}

int RMQ(int i,int j){
    
if(i>j){
        
int t=i;
        i
=j;
        j
=t;
    }
    
int k=log((double)j-i+1)/log((double)2);
    
if(dist[mn[i][k]]<=dist[mn[j-(1<<k)+1][k]])
        
return mn[i][k];
    
else
        
return mn[j-(1<<k)+1][k];
}

//////////////////////////////////////////////////////////////////////////
//main
int main(){
    
int i,j,u,v,weight,flag,w;
    init();
    vector
<PAIR> vec;
    scanf(
"%d%d%d",&n,&q,&st);
    
for(i=0;i<n-1;i++){
        scanf(
"%d%d%d",&u,&v,&weight);
        vec.push_back(make_pair(u,v));
        edg[ecnt].next
=p[u];
        edg[ecnt].v
=v;
        edg[ecnt].weight
=weight;
        p[u]
=ecnt++;
        edg[ecnt].next
=p[v];
        edg[ecnt].v
=u;
        edg[ecnt].weight
=weight;
        p[v]
=ecnt++;
    }

    dfs(
1,1,0);

//     for(i=1;i<maxorder;i++)
//         printf("%d ",order[i]);
//     printf("\n");
//     for(i=1;i<maxorder;i++)
//         printf("%d ",dist[i]);
//     printf("\n");
//     for(i=1;i<=n;i++)
//         printf("%d ",first[i]);
//     printf("\n");
//     for(i=1;i<=n;i++)
//         printf("%d ",last[i]);
//     printf("\n");

    build();
    preprocess();

    
for(i=0;i<q;i++){
        scanf(
"%d",&flag);
        
if(flag){
            scanf(
"%d%d",&j,&weight);
            j
--;
            u
=vec[j].first;
            v
=vec[j].second;
            
if(dist[first[u]]>dist[first[v]]){
                
int t=u;
                u
=v;
                v
=t;
            }
            w
=down(first[v])-down(first[u]);
            up(first[v],weight
-w);
            
if(last[v]+1<maxorder)
                up(last[v]
+1,w-weight);
        }
        
else{
            scanf(
"%d",&u);
            v
=order[RMQ(first[u],first[st])];
            printf(
"%d\n",down(first[u])+down(first[st])-2*down(first[v]));
            st
=u;
        }
    }
    
return 0;
}
            

 

 

posted @ 2009-01-24 11:59  Beetlebum  阅读(536)  评论(0编辑  收藏  举报