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
#include
#include
#include
#include
#include
#include
#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<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<>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<>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;i70000) cout<


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