SSLOJ2201 树

Description

Rayray现在在一棵有n个节点的树,现需要你按要求完成rayray给出的询问和修改操作。
询问操作,从当前点出发到目标点,rayray所需要的时间。执行完此操作后,rayray会跑去目标点。
修改操作:将rayray通过树上某条边的时间修改为w。

Input

第1行,3个整数n,q,s,分别表示树的节点个数,询问和修改操作的总数以及rayray在树上的起始点。
第2行到第n行,每行3个整数x,y,w,表示从x和y之间有一条边相连,w表示rayray通过这条边所要的时间。
接下来q行,每行先给出一个数c。
若c为0,代表询问操作,接下来会给出一个数d,代表目标点。
若c为1,代表修改操作,接下来会给出两个数i,w,代表把第i条边的时间修改为w。

Output

对于每个询问操作,输出一个整数(占一行),表示需要的时间。

Sample Input

3 3 1
1 2 1
2 3 2
0 2
1 2 3
0 3

Sample Output

1
3

Hint

数据范围
对于30%的数据,n,q<=1000;
对于100%的数据,n,q<=100000,1<=w<=10000。


做法很老,就是边权降点权,LCA,然后用什么数据结构维护一下点权的修改,ans就是dis[X]+dis[Y]-2*dis[LCA(X,Y)],虽然Oj上TLE了但是cena上AC了= =

LCA是用ST表做的,数据结构是线段树,最近不会写树状数组了= =当然树链剖分是可以徒手裸着做的= =

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#define LL long long
#define N 200005
using namespace std;
struct edge
{
       int num,w,y,next;
       }e[N*2];
int last[N],w[N],begin[N],end[N],times=0,bdfn[N];
int ls[N*4],rs[N*4],lazy[N*4];
int first[N],R[N*2],ver[N*2],dis[N],tot,f[N*2][20];
int n,m;

LL read()
{
	LL x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

void add(int x,int y,int z,int k)
{
     e[++tot].y=y;e[tot].next=last[x];e[tot].w=z;last[x]=tot;e[tot].num=k;
     e[++tot].y=x;e[tot].next=last[y];e[tot].w=z;last[y]=tot;e[tot].num=k;
     }
     
void dfs(int x,int dep,int pre,int key)
{
     begin[x]=++times; 
     w[x]=key; 
     ver[++tot]=x; first[x]=tot; R[tot]=dep; dis[x]=dis[pre]+key; 
     for (int i=last[x];i!=0;i=e[i].next)
         if (e[i].y!=pre)
         {
            dfs(e[i].y,dep+1,x,e[i].w);
            ver[++tot]=x;R[tot]=dep;bdfn[e[i].num]=e[i].y;
            }
     end[x]=times;
     }

int RMQ(int l,int r)
{
    int k=0;
    while (1<<(k+1)<=r-l+1) k++;
    int x=f[l][k],y=f[r-(1<<k)+1][k];
    return R[x]<R[y]?x:y;
}

int LCA(int x,int y)
{
    int l=first[x],r=first[y];
    if (l>r) swap(l,r);
    int res=RMQ(l,r);
    return ver[res];
}

void DP(int n)
{
     for (int i=1;i<=n;i++) f[i][0]=i;
     for (int j=1;(1<<j)<=n;j++)
         for (int i=1;i+(1<<j)-1<=n;i++)
         {
             int x=f[i][j-1],y=f[i+(1<<(j-1))][j-1];
             f[i][j]=R[x]<R[y]?x:y;
             }
     }
     
void build(int k,int l,int r)
{
     if (l==r)
     {
              ls[k]=rs[k]=l;
              lazy[k]=0;
              return;
              }
     int mid=(l+r)>>1;
     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
     ls[k]=l;rs[k]=r;
     }
     
void motifiy(int k,int l,int r,int val)
{
     if (ls[k]==l&&rs[k]==r)
     {
                            lazy[k]+=val;
                            return;
                            }
     int mid=(ls[k]+rs[k])>>1;
     if (r<=mid) motifiy(k<<1,l,r,val);
     else
     {
         if (l>mid) motifiy(k<<1|1,l,r,val);
         else
         {
             motifiy(k<<1,l,mid,val);motifiy(k<<1|1,mid+1,r,val);
             }
         }
     }
     
int query(int k,int x)
{
//    cout<<ls[k]<<' '<<rs[k]<<endl;
    if (ls[k]==rs[k]) return lazy[k];
    int mid=(ls[k]+rs[k])>>1;
    if (x>mid) return lazy[k]+query(k<<1|1,x);
    else return lazy[k]+query(k<<1,x);
}

int main()
{
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    n=read();m=read();int lastans=read();
    for (int i=1;i<n;i++)
    {
        int x=read(),y=read(),w=read();
        add(x,y,w,i);
        }
    tot=0;
    dfs(1,1,0,0);
    DP(2*n-1);
    build(1,1,n);
    for (int i=1;i<=m;i++)
    {
        int ch=read();
//        cout<<ch<<' '<<i<<endl;
        if (ch==0)
        {
                 int x=read();int y=LCA(lastans,x);
                 int ans=dis[lastans]+query(1,begin[lastans])+dis[x]+query(1,begin[x])-2*(dis[y]+query(1,begin[y]));
//                 cout<<y<<' '<<lastans<<' '<<x<<endl;
                 printf("%d\n",ans);
                 lastans=x;
                 }
        else
        {
            int x=read(),val=read();//if (i>70000) cout<<i<<' '<<end[bdfn[x]]<<' '<<w[bdfn[x]]<<endl;
            motifiy(1,begin[bdfn[x]],end[bdfn[x]],val-w[bdfn[x]]);
            w[bdfn[x]]=val;
//            cout<<"ok"<<endl;
            }
        }
    return 0;
}


你可能感兴趣的:(线段树,树,LCA)