SPOJ Query on a tree

此题需要把边权转换成点权,方法如下:
可以从根开始dfs,然后将每条边的值赋到向下的一个节点上,最后再把根的值赋为-∞即可。例如有一条1到2的边,权值为3,则从1开始dfs,就将2这个点的点权赋为3。
题目链接
Vjudge题目链接

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int T,n,tot,Head[20010],label,Next[20010],tree[20010],val[20010],a[80080],f[10010],bian[10010];
int size[10010],son[10010],num[10010],tid[10010],top[10010],fa[10010],dep[10010],number[20010];
bool visit[10010];
void Add(int x,int y,int z,int Num)
{
    tot++;
    Next[tot]=Head[x];
    Head[x]=tot;
    tree[tot]=y;
    val[tot]=z;
    number[tot]=Num;
}
void up(int x)
{
    a[x]=max(a[x*2],a[x*2+1]);
}
void build(int id,int l,int r)
{
    if (l==r) 
    {
        a[id]=f[num[l]];
        return;
    }
    int mid=(l+r)/2;
    build(id*2,l,mid);
    build(id*2+1,mid+1,r);
    up(id);
}
void Change_it(int x,int y,int d,int id,int l,int r)//此题单点修改 
{
    if (l>y||r<x) return;
    if (l>=x&&r<=y) 
    {
        a[id]=d;
        return;
    }
    int mid=(l+r)/2;
    Change_it(x,y,d,id*2,l,mid);
    Change_it(x,y,d,id*2+1,mid+1,r);
    up(id);
}
int Query_it(int x,int y,int id,int l,int r)
{
    if (l>y||r<x) return(-1<<29);
    if (l>=x&&r<=y) return a[id];
    int mid=(l+r)/2;
    int ans=max(Query_it(x,y,id*2,l,mid),Query_it(x,y,id*2+1,mid+1,r)); 
    return ans;
}
void Find_heavy_edge(int x,int father,int depth)
{
    fa[x]=father;dep[x]=depth;
    visit[x]=true;size[x]=1;son[x]=0;
    int maxsize=0;
    for (int i=Head[x];i;i=Next[i])
    if (!visit[tree[i]])
    {
        f[tree[i]]=val[i];bian[number[i]]=tree[i];
        Find_heavy_edge(tree[i],x,depth+1);
        size[x]+=size[tree[i]];
        if (maxsize<size[tree[i]])
        {
            maxsize=size[tree[i]];
            son[x]=tree[i];
        }
    }
}
void Connect_heavy_edge(int x,int ancestor)
{               
    visit[x]=true;
    label++;tid[x]=label;num[label]=x;top[x]=ancestor;
    if (son[x]!=0) Connect_heavy_edge(son[x],ancestor);
    for (int i=Head[x];i;i=Next[i])
    if (!visit[tree[i]])
    {
        Connect_heavy_edge(tree[i],tree[i]);
    }              
}
int Query(int x,int y)
{
    int ans=-1<<29;
    while(top[x]!=top[y])
    {
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        ans=max(ans,Query_it(tid[top[x]],tid[x],1,1,n));
        x=fa[top[x]];        
    }
    if (dep[x]>dep[y]) swap(x,y);
    ans=max(ans,Query_it(tid[x]+1,tid[y],1,1,n));
    return ans;
}                    
int main()
{
    scanf("%d",&T);
    for (int cas=1;cas<=T;cas++)
    {
        scanf("%d",&n);
        tot=0;
        for (int i=1;i<=n;i++) Head[i]=0;
        for (int i=1;i<=n-1;i++) 
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            Add(x,y,z,i);Add(y,x,z,i);
        }
        int root=1;
        f[root]=-1<<27;
        label=0;
        for (int i=1;i<=n;i++) visit[i]=false;
        Find_heavy_edge(root,0,1);
        for (int i=1;i<=n;i++) visit[i]=false;
        Connect_heavy_edge(root,root);
        build(1,1,n);
        char s[10];
        int x,y;
        while (true)
        {   
            scanf("%s",s);
            if (s[0]=='D') break;
            scanf("%d%d",&x,&y);
            if (s[0]=='Q') printf("%d\n",Query(x,y));
                else Change_it(tid[bian[x]],tid[bian[x]],y,1,1,n);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
洛谷的SPOJ需要注册一个SPOJ账号并进行绑定才能进行交题。您可以按照以下步骤进行注册: 1. 打开洛谷网站(https://www.luogu.com.cn/)并登录您的洛谷账号。 2. 在网站顶部导航栏中找到“题库”选项,将鼠标悬停在上面,然后选择“SPOJ”。 3. 在SPOJ页面上,您会看到一个提示,要求您注册SPOJ账号并进行绑定。点击提示中的链接,将会跳转到SPOJ注册页面。 4. 在SPOJ注册页面上,按照要求填写您的用户名、密码和邮箱等信息,并完成注册。 5. 注册完成后,返回洛谷网站,再次进入SPOJ页面。您会看到一个输入框,要求您输入刚刚注册的SPOJ用户名。输入用户名后,点击“绑定”按钮即可完成绑定。 现在您已经成功注册并绑定了SPOJ账号,可以开始在洛谷的SPOJ题库上刷题了。祝您顺利完成编程练习!\[1\]\[2\] #### 引用[.reference_title] - *1* *3* [(洛谷入门系列,适合洛谷新用户)洛谷功能全解](https://blog.csdn.net/rrc12345/article/details/122500057)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [luogu p7492 序列](https://blog.csdn.net/zhu_yin233/article/details/122051384)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值