SSLOJ2201 树

来源:互联网 发布:mac版本炒股软件 编辑:程序博客网 时间:2024/06/05 03:14

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 11 2 12 3 20 21 2 30 3

Sample Output

13

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 200005using 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;}


0 0
原创粉丝点击