SPOJ - QTREE Query on a tree (树链剖分+线段树单点更新,区间查询)

Query on a tree

 

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

题目链接:https://vjudge.net/problem/SPOJ-QTREE

题目大意:t组输入,有n个点,n-1条边,u,v,k是边的两端点和权值,有多条查询:

QUERY u,v  查询u到v的最短路径上的最大边权,CHANGE u,k   改变第u条边的权值为k , DONE   查询结束

思路:这道题和之前的题目不一样的地方在于它是每条边有一个权值,而不是每个点,那就可以把它转变成点带权,可以把每条边的权值赋给下面的那一点,也就是深度较大的那一点,可以发现除了根节点每个节点都对应着一条边的权。其余的就和之前的题差不多

注意:在求一条链上 x点到y点的最大边权的时候查询的应该是区间 [ id[ son[x] ] , id[y] ] ,而不是[ id[x] , id[y] ] 因为 id[x] 带的是它和它的父节点之间的边权,并不在路径上

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int N=10005;
int first[N],n,w[N],tot,cnt,maxx[N<<2];
int d[N],fa[N],siz[N],son[N],top[N],id[N],rk[N];
struct node
{
    int u,v,w,nex;
}e[N<<1];
void adde(int u,int v,int w)
{
    e[tot].u=u,e[tot].v=v;
    e[tot].w=w;
    e[tot].nex=first[u];
    first[u]=tot++;
}
void init()
{
    memset(first,-1,sizeof(first));
    memset(son,0,sizeof(son));
    tot=cnt=0;
}
void dfs1(int u,int pre,int depth) //处理 d,fa,siz,son 数组
{
    d[u]=depth;
    fa[u]=pre;
    siz[u]=1;
    for(int i=first[u];~i;i=e[i].nex)
    {
        int v=e[i].v;
        if(v==pre) continue;
        dfs1(v,u,depth+1);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])
            son[u]=v;
    }
}
void dfs2(int u,int t) //处理 top id rk wt 数组
{
    top[u]=t;
    id[u]=++cnt;
    rk[cnt]=u;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i=first[u];~i;i=e[i].nex)
    {
        int v=e[i].v;
        if(v!=son[u]&&v!=fa[u])
            dfs2(v,v);
    }
}
void pushup(int rt)
{
    maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        maxx[rt]=w[l];
        return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(int k,int c,int l,int r,int rt)
{
    if(l==r)
    {
        maxx[rt]=c;
        return;
    }
    int mid=(l+r)>>1;
    if(k<=mid) update(k,c,lson);
    else update(k,c,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
        return maxx[rt];
    int mid=(l+r)>>1,ans=0;
    if(L<=mid) ans=max(ans,query(L,R,lson));
    if(R>mid) ans=max(ans,query(L,R,rson));
    return ans;
}
int quemax(int x,int y)
{
    int ans=0;
    while(top[x]!=top[y])
    {
        if(d[top[x]]<d[top[y]]) swap(x,y);
        ans=max(ans,query(id[top[x]],id[x],1,n,1));
        x=fa[top[x]];
    }
    if(d[x]>d[y]) swap(x,y);
    ans=max(ans,query(id[son[x]],id[y],1,n,1));
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int u,v,k;
        scanf("%d",&n);
        init();
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&u,&v,&k);
            adde(u,v,k);
            adde(v,u,k);
        }
        dfs1(1,0,1);
        dfs2(1,1);
        for(int i=0;i<tot;i+=2)
        {
            if(d[e[i].u]<d[e[i].v]) swap(e[i].u,e[i].v);
            w[id[e[i].u]] = e[i].w;
        }
        build(1,n,1);
        char s[10];
        while(~scanf("%s",&s))
        {
            if(s[0]=='D') break;
            else if(s[0]=='C')
            {
                scanf("%d%d",&u,&k);
                update(id[e[u*2-2].u],k,1,n,1);
            }
            else if(s[0]=='Q')
            {
                scanf("%d%d",&u,&v);
                int ans=quemax(u,v);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值