Tree chain split (SPOJ 375)

This is a classic tree split chain of title.
It involves the maximum query sides.
Meaning of the questions:
give you n points, there are n-1 edges, two operations.
1. Edge between query "QUERY" x, y maximum
2. "CHANGE", the article edge weights x is the Y
3. In "DONE" End

This will be a point corresponding to an edge.
The trick of their own experience.
There are still differences between this and the point;

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define Set(aa,bb) memset(aa,bb,sizeof(aa))
#define begin Begin
#define to To
#define next Next
#define rank Rank
#define lr node<<1
#define rr node<<1|1
using namespace std;
const int maxn=10010<<2;
int n,sum;
int begin[maxn],to[maxn],w[maxn],next[maxn],e;
int tree[maxn],rank[maxn],top[maxn],dep[maxn],tid[maxn],son[maxn],size[maxn],fa[maxn],num[maxn];
struct md{
    int m,d,z;
}a[maxn];

void add(int x,int y,int z){
    to[++e]=y,next[e]=begin[x],begin[x]=e,w[e]=z;
}

void dfs1(int node,int father,int deep){
    dep[node]=deep;
    fa[node]=father;
    size[node]=1;
    for(int i=begin[node];i;i=next[i]){
        int u=to[i];
        if(u!=father){
            dfs1(u,node,deep+1);
            size[node]+=size[u];
            if(son[node]==-1 || size[u]>size[son[node]]) son[node]=u;
        }
    }
    return ;
}

void dfs2(int node,int high){
    top[node]=high;
    tid[node]=++sum;
    rank[tid[node]]=node;
    if(son[node]==-1) return ;
    dfs2(son[node],high);
    for(int i=begin[node];i;i=next[i]){
        int u=to[i];
        if(u!=fa[node] && u!=son[node]){
            dfs2(u,u);
        }
    }
    return ;
}

void push_up(int node){
    tree[node]=max(tree[lr],tree[rr]);
}

void create_tree(int node,int l,int r){
    if(l==r){
        tree[node]=num[l];
    //cout<<node<<": "<<l<<' '<<r<<' '<<tree[node]<<endl;
        return ;
    }
    int mid=(l+r)>>1;
    create_tree(lr,l,mid);
    create_tree(rr,mid+1,r);
    push_up(node);
    //cout<<node<<": "<<l<<' '<<r<<' '<<tree[node]<<endl;
    return ;
}

int query(int node,int l,int r,int be,int en){
    if(be<=l && en>=r){
        return tree[node];
    }
    int mid=(l+r)>>1;
    if(en<=mid)return query(lr,l,mid,be,en);
    if(be>mid) return query(rr,mid+1,r,be,en);
    return max(query(lr,l,mid,be,mid),query(rr,mid+1,r,mid+1,en));
}

int ask(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans=max(ans,query(1,1,n,tid[top[x]],tid[x]));
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    if(x!=y)ans=max(ans,query(1,1,n,tid[x]+1,tid[y]));
    return ans;
}

void update(int node,int l,int r,int be,int ad){
    if(l==r){
        tree[node]=ad;
        return ;
    }
    int mid=(l+r)>>1;
    if(be<=mid) update(lr,l,mid,be,ad);
    if(be>mid) update(rr,mid+1,r,be,ad);
    push_up(node);
    return ;
}

void change(int x,int y){
    if(dep[a[x].m]>dep[a[x].d]){
        update(1,1,n,tid[a[x].m],y);
    }else{
        update(1,1,n,tid[a[x].d],y);
    }
    return ;
}

void work(){
    e=0,sum=0;
    Set(begin,0),Set(son,-1);
    scanf("%d",&n);
    For(i,1,n-1){
        scanf("%d%d%d",&a[i].m,&a[i].d,&a[i].z);
        add(a[i].m,a[i].d,a[i].z);
        add(a[i].d,a[i].m,a[i].z);
    }
    dfs1(1,0,0);
    dfs2(1,1);
    For(i,1,n-1){
        if(dep[a[i].m]>dep[a[i].d]){
            num[tid[a[i].m]]=a[i].z;
        }else{
            num[tid[a[i].d]]=a[i].z;
        }
    }
    create_tree(1,1,n);
    while(1){
        char s[20];int x,y;
        scanf("%s",s);
        if(s[0]=='D') return;
        scanf("%d%d",&x,&y);
        if(s[0]=='Q'){
            printf("%d\n",ask(x,y));
        }else{
            change(x,y);
        }
    }
}

int main(){
    int _;
    scanf("%d",&_);
    while(_--) work();
    return 0;
}
Published 51 original articles · won praise 6 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_35776579/article/details/54564369