SPOJ375 Query on a tree 树链剖分

NC了,线段树UPDATE忘记PUSH_UP,WA了一个中午,整个人都晕了。

这次是边权的操作,那么把边权放在子节点就可以了。


375. Query on a tree

Problem code: QTREE

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.

We will ask you to perfrom some instructions of the following form:

  • CHANGE i ti : change the cost of the i-th edge to ti
    or
  • QUERY a b : ask for the maximum edge cost on the path from node a to node b

Input

The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.

For each test case:

  • In the first line there is an integer N (N <= 10000),
  • In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between ab of cost c (c <= 1000000),
  • The next lines contain instructions "CHANGE i ti" or "QUERY a b",
  • The end of each test case is signified by the string "DONE".

There is one blank line between successive tests.

Output

For each "QUERY" operation, write one integer representing its result.

Example

Input:
1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Output:
1
3

/*
NC了,线段树UPDATE忘记PUSH_UP,WA了一个中午,整个人都晕了。
这次是边权的操作,那么把边权放在子节点就可以了。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>

using namespace std;

#define INF 0x3fffffff
#define MAXN 10010

struct node
{
    int to,next,w;
}edge[9999999];

int a[MAXN],ID[MAXN];
int head[MAXN],en;
int belong[MAXN],idx[MAXN],qid[MAXN],f[MAXN],fi[MAXN];
int top[MAXN],len[MAXN];
int dep[MAXN],fat[MAXN],size[MAXN];
int Q[MAXN],vis[MAXN];
int n,cnt;

void add(int u,int v,int w)
{
    edge[en].to=v;
    edge[en].next=head[u];
    edge[en].w=w;
    head[u]=en++;
}

void split()
{
    int l,r;
    memset(dep,-1,sizeof(dep));
    l=0;
    dep[Q[r=1]=1]=0;
    fat[1]=-1;
    a[1]=-INF;
    while(l<r)
    {
        int x=Q[++l];
        vis[x]=0;
        for(int y=head[x];y!=-1;y=edge[y].next)
            if(dep[edge[y].to]==-1)
            {
                dep[Q[++r]=edge[y].to]=dep[x]+1;
                fat[edge[y].to]=x;
                a[edge[y].to]=edge[y].w; //将边权变为子节点点权
                ID[y/2+1]=edge[y].to;      //第i条边边权所在点
            }
    }
    cnt=0;
    for(int i=n;i;i--)
    {
        int x=Q[i],p=-1;
        size[x]=1;
        for(int y=head[x];y!=-1;y=edge[y].next)
            if(vis[edge[y].to])
            {
                size[x]+=size[edge[y].to];
                if(p==-1||size[edge[y].to]>size[p])
                    p=edge[y].to;
            }
        if(p==-1)
        {
            idx[x]=len[++cnt]=1;
            belong[top[cnt]=x]=cnt;
        }
        else
        {
            idx[x]=++len[belong[x]=belong[p]];
            top[belong[x]]=x;
        }
        vis[x]=true;
    }
}

void getqid()
{
    fi[1]=1;
    for(int i=2;i<=cnt;i++)
        fi[i]=fi[i-1]+len[i-1];
    for(int i=1;i<=n;i++)
    {
        int blo=belong[i];
        qid[i]=fi[blo]+len[blo]-idx[i];
        f[qid[i]]=i;
    }
}

int query(int l,int r,int root,int L,int R);
int research(int x,int y)
{
    int ret=0;
    while(belong[x]!=belong[y])
    {
        if(dep[top[belong[x]]]<dep[top[belong[y]]])
            swap(x,y);
        ret=max(query(1,n,1,qid[top[belong[x]]],qid[x]),ret);
        x=fat[top[belong[x]]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    //x的点权是fat[x]到x的边权,需要特殊处理
    int l,r;
    if(x!=y) l=qid[x]+1,r=qid[y];
    else return ret;
    ret=max(query(1,n,1,l,r),ret); //其他数据结构维护区间值
    return ret;
}

#define lson l,m,root<<1
#define rson m+1,r,root<<1|1

int node[MAXN<<2];

void push_up(int root)
{
    node[root]=max(node[root<<1],node[root<<1|1]);
}

void build(int l,int r,int root)
{
    if(l==r)
    {
        node[root]=a[f[l]];
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(root);
}

void update(int l,int r,int root,int a,int d)
{
    if(l==r)
    {
        node[root]=d;
        return;
    }
    int m=(l+r)>>1;
    if(a<=m)
        update(lson,a,d);
    else
        update(rson,a,d);
    push_up(root);
}

int query(int l,int r,int root,int L,int R)
{
    if(l>=L && r<=R)
    {
        return node[root];
    }
    int m=(l+r)>>1;
    int ret=-INF;
    if(L<=m)
        ret=max(ret,query(lson,L,R));
    if(R>m)
        ret=max(ret,query(rson,L,R));
    return ret;
}


int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int u,v,w;
        scanf("%d",&n);
        memset(head,-1,sizeof(head));en=0;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        split();
        getqid();
        build(1,n,1);
        char str[200];
        while(~scanf("%s",str))
        {
            if(strcmp(str,"DONE")==0)
                break;
            scanf("%d%d",&u,&v);
            if(str[0]=='C')
            {
                u=ID[u];
                update(1,n,1,qid[u],v);
            }
            else
            {
                printf("%d\n",research(u,v));
            }
        }

    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值