SPOJ - QTREE(树链剖分+单点更新+区间最大值查询)

题意:给出n个点n-1条边的树,有两个操作,一个是查询节点l到r的边的最大值,然后指定边的更改权值。

题解:差不多是树链剖分的模版题,注意每个点表示的边是连向其父亲节点的边。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int M = 1e4 + 10;
struct Edge {
    int v , next;
}edge[M << 1];
int head[M] , e;
int top[M];
int fa[M];
int p[M];
int fp[M];
int son[M];
int deep[M];
int num[M];
int pos;
void init() {
    memset(head , -1 , sizeof(head));
    memset(son , -1 , sizeof(son));
    e = 0;
    pos = 0;
}
void add(int u , int v) {
    edge[e].v = v;
    edge[e].next = head[u];
    head[u] = e++;
}
void dfs1(int u , int pre , int d) {
    deep[u] = d;
    fa[u] = pre;
    num[u] = 1;
    for(int i = head[u] ; i != -1 ; i = edge[i].next) {
        int v = edge[i].v;
        if(v != pre) {
            dfs1(v , u , d + 1);
            num[u] += num[v];
            if(son[u] == -1 || num[son[u]] < num[v])
                son[u] = v;
        }
    }
}
void getpos(int u , int sp) {
    top[u] = sp;
    p[u] = pos++;
    fp[p[u]] = u;
    if(son[u] == -1)
        return ;
    getpos(son[u] , sp);
    for(int i = head[u] ; i != -1 ; i = edge[i].next) {
        int v = edge[i].v;
        if(son[u] != v && v != fa[u]) {
            getpos(v , v);
        }
    }
}
struct TnT {
    int l , r , MAX;
}T[M << 2];
void pushup(int i) {
    T[i].MAX = max(T[i << 1].MAX , T[(i << 1) | 1].MAX);
}
void build(int l , int r , int i) {
    int mid = (l + r) >> 1;
    T[i].l = l , T[i].r = r , T[i].MAX = 0;
    if(T[i].l == T[i].r)
        return ;
    build(l , mid , i << 1);
    build(mid + 1 , r , (i << 1) | 1);
    pushup(i);
}
void updata(int pos , int i , int ad) {
    int mid = (T[i].l + T[i].r) >> 1;
    if(T[i].l == pos && T[i].r == pos) {
        T[i].MAX = ad;
        return ;
    }
    if(mid < pos) {
        updata(pos , (i << 1) | 1 , ad);
    }
    else {
        updata(pos , i << 1 , ad);
    }
    pushup(i);
}
int query(int l , int r , int i) {
    int mid = (T[i].l + T[i].r) >> 1;
    if(T[i].l == l && T[i].r == r) {
        return T[i].MAX;
    }
    pushup(i);
    if(mid < l) {
        return query(l , r , (i << 1) | 1);
    }
    else if(mid >= r) {
        return query(l , r , i << 1);
    }
    else {
        return max(query(l , mid , i << 1) , query(mid + 1 , r , (i << 1) | 1));
    }
}
int find(int u , int v) {
    int f1 = top[u] , f2 = top[v];
    int tmp = 0;
    while(f1 != f2) {
        if(deep[f1] < deep[f2]) {
            swap(f1 , f2);
            swap(u , v);
        }
        tmp = max(tmp , query(p[f1] , p[u] , 1));
        u = fa[f1] , f1 = top[u];
    }
    if(u == v) return tmp;
    if(deep[u] > deep[v]) swap(u , v);
    return max(tmp , query(p[son[u]] , p[v] , 1));
}
int ed[M][3];
int main() {
    int t , n , u , v;
    scanf("%d" , &t);
    while(t--) {
        scanf("%d" , &n);
        init();
        for(int i = 0 ; i < n - 1 ; i++) {
            for(int j = 0 ; j < 3 ; j++) {
                scanf("%d" , &ed[i][j]);
            }
            add(ed[i][0] , ed[i][1]);
            add(ed[i][1] , ed[i][0]);
        }
        dfs1(1 , 0 , 0);
        getpos(1 , 1);
        build(0 , pos , 1);
        for(int i = 0 ; i < n - 1 ; i++) {
            if(deep[ed[i][0]] > deep[ed[i][1]])
                swap(ed[i][0] , ed[i][1]);
            updata(p[ed[i][1]] , 1 , ed[i][2]);
        }
        char cp[10];
        while(scanf("%s" , cp)) {
            if(cp[0] == ‘D‘)
                break;
            scanf("%d%d" , &u , &v);
            if(cp[0] == ‘C‘) {
                updata(p[ed[u - 1][1]] , 1 , v);
            }
            else {
                printf("%d\n" , find(u , v));
            }
        }
    }
    return 0;
}
时间: 2024-08-06 16:05:34

SPOJ - QTREE(树链剖分+单点更新+区间最大值查询)的相关文章

HDU 5274 Dylans loves tree(LCA+dfs时间戳+成段更新 OR 树链剖分+单点更新)

Problem Description Dylans is given a tree with N nodes. All nodes have a value A[i].Nodes on tree is numbered by 1∼N. Then he is given Q questions like that: ①0 x y:change node x′s value to y ②1 x y:For all the value in the path from x to y,do they

【学术篇】SPOJ QTREE 树链剖分

发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧.. WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能得28pts.. 重新见到这些失踪的dalao灰常开心, 于是想让自己心情稍微差一点, 就想着把自己昨天写WA的QTREE重构一遍吧.. 于是重构的sb链剖果然挂掉了... 出现了各种各样的漏洞... 忘记各种各样的句子, 然而退化成了暴力小数据也随便过看不出来啊~~~ 但是还是在1h之内调对了_(

SPOJ QTREE 树链剖分

375. Query on a tree Problem code: QTREE 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

poj 2763 Housewife Wind(树链剖分+单点查询+区间修改)

题目链接:http://poj.org/problem?id=2763 题意:给一个数,边之间有权值,然后两种操作,第一种:求任意两点的权值和,第二,修改树上两点的权值. 题解:简单的树链剖分. #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int M = 1e5 + 10; struct Edge { int v , next; }edge[M &

SPOJ375.QTREE树链剖分

题意:一个树,a b c 代表a--b边的权值为c.CHANGE x y  把输入的第x条边的权值改为y,QUERY x y 查询x--y路径上边的权值的最大值. 第一次写树链剖分,其实树链剖分只能说是一种思想.树链剖分  就是 先选择从根节点到叶子节点的最长的路径的权值对应到线段树上,然后从一个子树的根节点到叶子的最长路径的权值对应到线段树上这样直到把所有的点都处理了,然后就是线段树区间查询最值了. 具体可以看这个博客.http://blog.sina.com.cn/s/blog_6974c8

SPOJ 375 树链剖分

点击打开链接 题意:给个树和树上的权值,两个操作,Q u v,问u到v的边上的最大权值,C u v,将第u条边的权值改为v 思路:今天学了学树链剖分,这题是个检验模版的题目,理论我是解释不清楚的,自己在九野聚聚那学来的一份模版 #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <a

一维 + 二维树状数组 + 单点更新 + 区间更新 详解

树状数组详解: 假设一维数组为A[i](i=1,2,...n),则与它对应的树状数组C[i](i=1,2,...n)是这样定义的: C1 = A1 C2 = A1 + A2 C3 = A3 C4 = A1 + A2 + A3 + A4 C5 = A5 C6 = A5 + A6 ................. C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 ................ 如图可知: 为奇数的时候他是代表他本身,而为偶数的时候则是代表着自

hdu 1556Color the ball (树状数组,更新区间,查询单点)

Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12566    Accepted Submission(s): 6294 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气

线段树单点更新区间最大值 hdoj1754I Hate It

题目:hdoj1754 I  Hate It 分析:更新的话,建树的时候保存叶子编号的的节点信息,然后从下往上更新就ok. 求和的话,从根节点开始,然后找在根的左边还是右边,然后递归找一个所有中的最大值即可. 代码: #include <cstdio> #include <algorithm> #include <iostream> using namespace std; const int N = 205000; struct Node { int l,r; int