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(树链剖分模版)

Query on a tree Time Limit: 5000MS   Memory Limit: Unknown   64bit IO Format: %l...

spoj375 Query on a tree 树链剖分

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

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, ...

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,...

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

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

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

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

【SPOJ 375】Query on a tree&树链剖分详解

SPOJ 375题意给你一棵树每条边的权值,有两种操作:修改某一条边的权值;询问两点之间的路径和。(多组数据)样例输入13 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 ...

spoj 375 Query on a tree 树链剖分

题目连接:http://www.spoj.com/problems/QTREE/ 题目大意:给你一棵树

SPOJ 375 QTREE Query on a tree 树链剖分

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

SPOJ375--Query on a tree(树链剖分)

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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