zoukankan      html  css  js  c++  java
  • SPOJ 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




    模板题
    2种操作:
    1.把第i条边的边权更改为v
    2.查询路径u,v中最大的边权


    注意:是边权,所以查询时候u,v的lca不能包括进来
    因为lca所表示的边权并没有在u,v的路径中

    树链剖分+线段树(单点更新,区间查询)
    线段树连lazy都不用


    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    #define LL long long
    #define debug printf("eeeeeeeeeeeeeeeeeeeee")
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    const int maxn=1e4+10;
    const int inf=0x3f3f3f3f;
    
    int dep[maxn];
    int son[maxn];
    int siz[maxn];
    int top[maxn];
    int fa[maxn];
    int chg[maxn];
    int rev[maxn];
    int cost[maxn];
    int e[maxn][3];
    
    struct Edge
    {
        int to,next;
    };
    Edge edge[maxn<<1];
    int head[maxn];
    int tot;
    
    int ma[maxn<<2];
    
    void init()
    {
        memset(head,-1,sizeof head);
        tot=0;
    }
    
    void addedge(int u,int v)
    {
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    
    void solve(int );
    
    int main()
    {
        int test;
        scanf("%d",&test);
        while(test--){
            int n;
            init();
            scanf("%d",&n);
            for(int i=1;i<n;i++){
                scanf("%d %d %d",&e[i][0],&e[i][1],&e[i][2]);
                addedge(e[i][0],e[i][1]);
                addedge(e[i][1],e[i][0]);
            }
            solve(n);
        }
        return 0;
    }
    
    void dfs0(int u,int pre)
    {
        fa[u]=pre;
        siz[u]=1;
        dep[u]=dep[pre]+1;
        for(int i=head[u];~i;i=edge[i].next){
            int v=edge[i].to;
            if(v==pre)
                continue;
            dfs0(v,u);
            siz[u]+=siz[v];
            if(son[u]==-1 || siz[v]>siz[son[u]])
                son[u]=v;
        }
    }
    
    void dfs1(int u,int tp)
    {
        top[u]=tp;
        chg[u]=++tot;
        rev[tot]=u;
        if(son[u]==-1)
            return ;
        dfs1(son[u],tp);
        for(int i=head[u];~i;i=edge[i].next){
            int v=edge[i].to;
            if(v==fa[u] || v==son[u])
                continue;
            dfs1(v,v);
        }
    }
    
    void pushup(int rt)
    {
        ma[rt]=max(ma[rt<<1],ma[rt<<1|1]);
    }
    
    void build(int l,int r,int rt)
    {
        if(l==r){
            ma[rt]=cost[rev[l]];
            return ;
        }
        int m=(l+r)>>1;
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void update(int p,int add,int l,int r,int rt)
    {
        if(l==r){
            ma[rt]=add;
            return ;
        }
        int m=(l+r)>>1;
        if(p<=m)
            update(p,add,lson);
        else
            update(p,add,rson);
        pushup(rt);
    }
    
    int query(int L,int R,int l,int r,int rt)
    {
        if(L<=l && R>=r){
            return ma[rt];
        }
        int m=(l+r)>>1;
        int ret=-inf;
        if(L<=m)
            ret=max(ret,query(L,R,lson));
        if(R>m)
            ret=max(ret,query(L,R,rson));
        return ret;
    }
    
    int query_path(int u,int v)
    {
        int ret=-inf;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])
                swap(u,v);
            ret=max(ret,query(chg[top[u]],chg[u],1,tot,1));
            u=fa[top[u]];
        }
        if(dep[u]<dep[v])
            swap(u,v);
        ret=max(ret,query(chg[v]+1,chg[u],1,tot,1));
        return ret;
    }
    
    void solve(int n)
    {
        memset(dep,0,sizeof dep);
        memset(son,-1,sizeof son);
        memset(cost,0,sizeof cost);
        dfs0(1,1);
        tot=0;
        dfs1(1,1);
        for(int i=1;i<n;i++){
            if(dep[e[i][0]]>dep[e[i][1]])
                swap(e[i][0],e[i][1]);
            cost[e[i][1]]=e[i][2];
        }
        build(1,tot,1);
        char str[15];
        while(scanf("%s",str)){
            if(str[0]=='D')
                break;
            int u,v;
            scanf("%d %d",&u,&v);
            if(str[0]=='Q'){
                printf("%d
    ",query_path(u,v));
            }
            else{
                update(chg[e[u][1]],v,1,tot,1);
            }
        }
        return ;
    }









  • 相关阅读:
    副业收入是我做程序员的2倍!副业这么有 “钱”景,我要考虑转行吗?
    C语言丨const关键字的用法详解
    C/C++学习笔记:C/C++函数调用的方式,你应该要学会这五种
    软件崩溃了,该如何解决? 解决问题的关键要会对症下药!
    C语言丨深入理解volatile关键字
    C语言丨getch(),getche()和getchar()的区别
    学编程的误区——眼高手低,不重视练习!
    通过编写“猜测数字”游戏来探索Linux中的Bash
    零基础想要更快入门Linux?找对方法,让你少奋斗10年!
    VS/VC 出现闪退怎么办?这4个技巧要知道!
  • 原文地址:https://www.cnblogs.com/-maybe/p/4883363.html
Copyright © 2011-2022 走看看