SPOJ 375 Query on a tree(初学树链剖分)

原创 2015年07月07日 23:12:21

QTREE - Query on a tree

no tags 

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


大致题意:一棵1e4节点的树,进行两种操作,1.把第i条边权值改为x 2.查询a到b路径上的最大边权


树链剖分教程http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

学了树链剖分,这种算法是把树hash到了几段连续的区间上,分重链和轻链为连续的区间,可以证明任何两点间路径都可以分为logn复杂度的重链和轻链,也就是连续区间,然后再用线段树等算法在这些区间上处理问题


显然本题也是这样,剖分过程On复杂度,两次dfs,用在logn的复杂度套上线段树nlogn,总复杂度是nlogn*logn

14620018 2015-07-07 17:10:34 ka Query on a tree acceptededit    ideone it 0.44 3.9M C++ 4.9
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define refeach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;

const int N = 1e4+100;
struct Edge
{
    int u,v,w,nxt;
    Edge(){}
    Edge(int u,int v,int w,int nxt) : u(u),v(v),w(w),nxt(nxt) {}
}es[N<<1];
int head[N];
int ecnt;
int n;
inline void add_edge(int u,int v,int w)
{
    es[++ecnt] = Edge(u,v,w,head[u]);
    head[u] = ecnt;
    es[ecnt+n] = Edge(v,u,w,head[v]);
    head[v] = ecnt+n;
}

int dep[N],son[N],sz[N],fa[N];
void dfs1(int u)
{
    dep[u] = dep[fa[u]]+1;
    son[u] = 0,sz[u] = 1;
    for(int i = head[u];~i;i=es[i].nxt)
    {
        int v = es[i].v;
        if(fa[u] == v) continue;
        fa[v] = u;
        dfs1(v);
        sz[u] += sz[v];
        if(sz[v] > sz[son[u]]) son[u] = v;
    }
}

int tp[N],tid[N];
int indx;
void dfs2(int u,int ance)
{
    tid[u] = ++indx;
    tp[u] = ance;
    if(son[u]) dfs2(son[u],ance);
    for(int i = head[u];~i;i=es[i].nxt)
    {
        int v = es[i].v;
        if(v == fa[u]) continue;
        if(v != son[u]) dfs2(v,v);
    }
}
#define root 1,indx,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int maxn[N<<2];
inline void pushup(int rt)
{
    maxn[rt] = max(maxn[rt<<1],maxn[rt<<1|1]);
}
void update(int pos,int x,int l,int r,int rt)
{
    if(l == r)
    {
        maxn[rt] = x;
        return ;
    }
    int m = (l+r)>>1;
    if(pos <= m) update(pos,x,lson);
    else update(pos,x,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L <= l && r <= R) return maxn[rt];
    int maxx = 0;
    int m = (l+r)>>1;
    if(L <= m) maxx = max(maxx,query(L,R,lson));
    if(R >= m+1) maxx = max(maxx,query(L,R,rson));
    return maxx;
}

int solve(int u,int v)
{
    int anceu = tp[u],ancev = tp[v];
    int maxx = 0;
    while(anceu != ancev)
    {
        if(dep[anceu] < dep[ancev]) swap(anceu,ancev),swap(u,v);
        maxx = max(maxx,query(tid[anceu],tid[u],root));
        u = fa[anceu];
        anceu = tp[u];
    }
    if(u == v) return maxx;
    if(dep[u] < dep[v]) return max(maxx,query(tid[son[u]],tid[v],root));
    else return max(maxx,query(tid[son[v]],tid[u],root));
}
void ini()
{
    memset(head,-1,sizeof(head));
    indx = ecnt = 0;
    memset(maxn,0,sizeof(maxn));
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ini();
        scanf("%d",&n);
        REP(i,n-1)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add_edge(u,v,w);
        }
        char op[20];
        dfs1(1);
        dfs2(1,1);
        REP(i,n-1)
        {
            int u = es[i].u,v = es[i].v , w = es[i].w;
            if(dep[v] < dep[u]) swap(es[i].u,es[i].v);
            update(tid[es[i].v],w,root);
        }
        while(scanf("%s",op))
        {
            if(op[0] == 'D') break;
            if(op[0] == 'Q')
            {
                int u,v;
                scanf("%d%d",&u,&v);
                printf("%d\n",solve(u,v));
            }
            else
            {
                int id,x;
                scanf("%d%d",&id,&x);
                update(tid[es[id].v],x,root);
            }
        }
    }
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

【树链剖分模板】【SPOJ 375】 Query on a tree

树链剖分模板~ 【SPOJ 375】 Query on a tree
  • Regina8023
  • Regina8023
  • 2014年12月05日 06:33
  • 1101

spoj 375. Query on a tree 【树链剖分--插点问线 】

题目:spoj 375. Query on a tree 题意:题意很清晰,就是给你一颗树,每两点之间有权值,然后改变一些权值,问一条路径上的最大值。 分析:入门题目,直接套树链模...
  • y990041769
  • y990041769
  • 2014年10月21日 11:43
  • 1779

SPOJ375——Query on a tree(树链剖分模板详解以及入门)

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
  • say_c_box
  • say_c_box
  • 2016年08月05日 10:42
  • 1423

spoj 375 Query on a tree 树链剖分

题目连接:http://www.spoj.com/problems/QTREE/ 题目大意:给你一棵树
  • u014076176
  • u014076176
  • 2014年09月03日 19:04
  • 401

SPOJ 375 QTREE Query on a tree 树链剖分

题目:http://www.spoj.com/problems/QTREE/en/ 题意:给定一棵有n个点的树,每条边都有权值。有两种操作,第一种是询问两点间路径上边权的最大值,第二种是改变...
  • discreeter
  • discreeter
  • 2016年05月13日 23:06
  • 287

spoj 375 Query on a tree(树链剖分模版)

Query on a tree Time Limit: 5000MS   Memory Limit: Unknown   64bit IO Format: %l...
  • WEYuLi
  • WEYuLi
  • 2014年08月12日 20:54
  • 541

SPOJ 375. Query on a tree (基于边的树链剖分)

基于边的树链剖分,与点的几个不同点: 1,维护边权值,即是维护某点与其父亲点之间边的权值,所以可以等同视为该点的权值(即孩子结点,可以通过判断深度较大的是孩子结点)。 2,在LCA过程中,最后一步...
  • rockzh1993
  • rockzh1993
  • 2015年10月07日 23:25
  • 175

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

QTREE - Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes,...
  • JiaYuzun
  • JiaYuzun
  • 2017年03月17日 18:19
  • 223

spoj375 Query on a tree 树链剖分

题意:在一棵n个点构成的树上有两个操作。1.修改某条边的边权   2.查询两点之间最大的边权 思路:基础的树链剖分。参见的是http://blog.sina.com.cn/s/blog_6974...
  • u011645923
  • u011645923
  • 2015年01月20日 19:05
  • 549

spoj 375 Query on a tree——(树链剖分orLCT动态树)

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
  • ergedathouder
  • ergedathouder
  • 2017年01月21日 22:22
  • 174
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SPOJ 375 Query on a tree(初学树链剖分)
举报原因:
原因补充:

(最多只允许输入30个字)