zoukankan      html  css  js  c++  java
  • SPOJ375(树链剖分)

    题目:Query on a tree

    题意:给定一棵树,告诉了每条边的权值,然后给出两种操作:

    (1)把第i条边的权值改为val

    (2)询问a,b路径上权值最大的边

    分析:本题与HDU3966差不多,区别就是:HDU3966是告诉树中点权的值,这里是边权。

    所以我们可以转化,用边的孩子节点来表示该边。

    #include <iostream>
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    
    using namespace std;
    const int N=50010;
    const int INF=1<<30;
    
    int n,tim;
    
    int num[N],siz[N],top[N],son[N];
    int dep[N],tid[N],rank[N],fa[N];
    int head[N],to[2*N],next[2*N],w[2*N],edge;
    
    struct Edge
    {
        int u,v,c;
    };
    Edge tmp[2*N];
    
    void Init()
    {
        memset(head,-1,sizeof(head));
        memset(son,-1,sizeof(son));
        tim=0;
        edge=0;
    }
    
    void addedge(int u,int v,int c)
    {
        to[edge]=v,w[edge]=c,next[edge]=head[u],head[u]=edge++;
        to[edge]=u,w[edge]=c,next[edge]=head[v],head[v]=edge++;
    }
    
    //树链剖分部分
    void dfs1(int u,int father,int d)
    {
        dep[u]=d;
        fa[u]=father;
        siz[u]=1;
        for(int i=head[u]; ~i; i=next[i])
        {
            int v=to[i];
            if(v!=father)
            {
                dfs1(v,u,d+1);
                siz[u]+=siz[v];
                if(son[u]==-1||siz[v]>siz[son[u]])
                    son[u]=v;
            }
        }
    }
    
    void dfs2(int u,int tp)
    {
        top[u]=tp;
        tid[u]=++tim;
        rank[tid[u]]=u;
        if(son[u]==-1) return;
        dfs2(son[u],tp);
        for(int i=head[u]; ~i; i=next[i])
        {
            int v=to[i];
            if(v!=son[u]&&v!=fa[u])
                dfs2(v,v);
        }
    }
    
    //线段树部分
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    
    int MAX[4*N];
    
    void PushUP(int rt)
    {
        MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]);
    }
    
    void Build(int l,int r,int rt)
    {
        if(l==r)
        {
            MAX[rt]=num[l];
            return;
        }
        int mid=(l+r)>>1;
        Build(lson);
        Build(rson);
        PushUP(rt);
    }
    
    void Update(int l,int r,int rt,int p,int val)
    {
        if(l==r)
        {
            MAX[rt]=val;
            return;
        }
        int mid=(l+r)>>1;
        if(p<=mid)
            Update(lson,p,val);
        else
            Update(rson,p,val);
        PushUP(rt);
    }
    
    int Query(int l,int r,int rt,int L,int R)
    {
        if(L<=l&&R>=r)
            return MAX[rt];
        int mid=(l+r)>>1;
        int ret=-INF;
        if(L<=mid) ret=max(ret,Query(lson,L,R));
        if(R>mid)  ret=max(ret,Query(rson,L,R));
        return ret;
    }
    
    void Change(int x,int val)
    {
        if(dep[tmp[x].u]>dep[tmp[x].v])
            Update(2,n,1,tid[tmp[x].u],val);
        else
            Update(2,n,1,tid[tmp[x].v],val);
    }
    
    int query(int x,int y)
    {
        int ans=-INF;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            ans=max(ans,Query(2,n,1,tid[top[x]],tid[x]));
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        if(x!=y) ans=max(ans,Query(2,n,1,tid[x]+1,tid[y]));
        return ans;
    }
    
    int main()
    {
        char oper[15];
        int a,b,c,t;
        scanf("%d",&t);
        while(t--)
        {
            Init();
            scanf("%d",&n);
            for(int i=1; i<n; i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                tmp[i].u=a;tmp[i].v=b;tmp[i].c=c;
                addedge(a,b,c);
            }
            dfs1(1,1,1);
            dfs2(1,1);
            //用边的孩子节点来表示该边
            for(int i=1;i<n;i++)
            {
                if(dep[tmp[i].u]>dep[tmp[i].v])
                    num[tid[tmp[i].u]]=tmp[i].c;
                else
                    num[tid[tmp[i].v]]=tmp[i].c;
            }
            Build(2,n,1);
            while(1)
            {
                scanf("%s",oper);
                if(oper[0]=='D') break;
                scanf("%d%d",&a,&b);
                if(oper[0]=='Q')
                    printf("%d
    ",query(a,b));
                else
                    Change(a,b);
            }
        }
        return 0;
    }
    


     

  • 相关阅读:
    基于ZYNQ XC7Z045 FFG 900的高性能计算模块
    linux TCP数据包封装在SKB的过程分析
    关于 linux中TCP数据包(SKB)序列号的小笔记
    TCP的TIME_WAIT状态
    Linux-2.6.25 TCPIP函数调用大致流程
    Linux 下不经过BIOS重启(i386)
    Linux块设备加密之dm-crypt分析
    Device Mapper 代码分析
    Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 3 部分: Systemtap
    Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 2 部分: DTrace
  • 原文地址:https://www.cnblogs.com/pangblog/p/3294084.html
Copyright © 2011-2022 走看看