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_6974c8b20100zc61.html

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <algorithm>
  6 using namespace std;
  7 typedef unsigned long long ull;
  8 typedef long long ll;
  9 const int inf = 0x3f3f3f3f;
 10 const double eps = 1e-8;
 11 const int maxn = 1e4+10;
 12 int top[maxn],fa[maxn],son[maxn],dep[maxn],siz[maxn],seg_tree[maxn<<2],head[maxn],pos[maxn];
 13 int edge,tot;
 14 struct
 15 {
 16     int to,next;
 17 }e[maxn<<1];
 18 void add(int x,int y)
 19 {
 20     e[edge].to = y;
 21     e[edge].next = head[x];
 22     head[x] = edge++;
 23 }
 24
 25 void dfs(int r)
 26 {
 27     siz[r] = 1;
 28     son[r] = 0;
 29     for (int i = head[r]; i > 0; i = e[i].next)
 30         if (fa[r] != e[i].to)
 31         {
 32             dep[e[i].to] = dep[r] + 1;
 33             fa[e[i].to] = r;
 34             dfs(e[i].to);
 35             if (siz[e[i].to] > siz[son[r]])
 36                 son[r] = e[i].to;
 37             siz[r] += siz[e[i].to];
 38         }
 39 }
 40
 41 void build(int r,int f)
 42 {
 43     pos[r] = tot++;
 44     top[r] = f;
 45     if (son[r] > 0)
 46         build(son[r],top[r]);
 47     for (int i = head[r]; i > 0; i = e[i].next)
 48     {
 49         if (fa[r] != e[i].to && son[r] != e[i].to)
 50             build(e[i].to,e[i].to);
 51     }
 52 }
 53
 54 void update(int l,int r,int o,int x,int v)
 55 {
 56     if (l == r)
 57     {
 58         seg_tree[o] = v;
 59         return;
 60     }
 61     int mid = (l + r) >> 1;
 62     if (x <= mid)
 63         update(l,mid,o<<1,x,v);
 64     if (x > mid)
 65         update(mid+1,r,o<<1|1,x,v);
 66     seg_tree[o] = max(seg_tree[o<<1],seg_tree[o<<1|1]);
 67 }
 68
 69 int query(int l,int r,int o,int ua,int ub)
 70 {
 71     if (ua <= l && ub >= r)
 72         return seg_tree[o];
 73     int mid = (l + r) >> 1;
 74     int t1,t2;
 75     t1 = t2 = 0;
 76     if (ua <= mid)
 77         t1 = query(l,mid,o<<1,ua,ub);
 78     if (ub > mid)
 79         t2 = query(mid+1,r,o<<1|1,ua,ub);
 80     return max(t1,t2);
 81 }
 82
 83 int get_max(int ua,int ub)
 84 {
 85     int f1 = top[ua];
 86     int f2 = top[ub];
 87     int tmp = 0;
 88     while (f1 != f2)
 89     {
 90         if (dep[f1] < dep[f2])
 91             swap(f1,f2),swap(ua,ub);
 92         tmp = max(tmp,query(1,tot,1,pos[f1],pos[ua]));
 93         ua = fa[f1],f1 = top[ua];
 94     }
 95     if (ua == ub)
 96         return tmp;
 97     if (dep[ua] > dep[ub])
 98         swap(ua,ub);
 99     tmp = max(tmp,query(1,tot,1,pos[son[ua]],pos[ub]));
100     return tmp;
101 }
102
103 int d[maxn][3];
104 void init()
105 {
106     int n;
107     scanf ("%d",&n);
108     memset(dep,0,sizeof(dep));
109     memset(son,0,sizeof(son));
110     memset(head,0,sizeof(head));
111     memset(fa,0,sizeof(fa));
112     memset(top,0,sizeof(top));
113     int root = (n+1)>>1;
114     fa[root] = dep[root] =0;
115     tot = edge = 1;
116     int a,b,c;
117     for (int i = 1; i < n; i++)
118     {
119         scanf ("%d%d%d",&a,&b,&c);
120         add(a,b),add(b,a);
121         d[i][0] = a,d[i][1] = b,d[i][2] = c;
122     }
123     dfs(root);
124     build(root,root);
125     tot--;
126     for (int i = 1; i < n; i++)
127     {
128         if (dep[d[i][0]] < dep[d[i][1]])
129             swap(d[i][1],d[i][0]);
130         update(1,tot,1,pos[d[i][0]],d[i][2]);
131     }
132
133 }
134 int main(void)
135 {
136     #ifndef ONLINE_JUDGE
137         freopen("in.txt","r",stdin);
138     #endif // ONLINE_JUDGE
139     int t;
140     scanf ("%d",&t);
141     while (t--)
142     {
143          init();
144          char op[10];
145          while (scanf ("%s",op),op[0] != ‘D‘)
146          {
147              int x,y;
148              scanf ("%d%d",&x,&y);
149              if (op[0] == ‘C‘)
150                 update(1,tot,1,pos[d[x][0]],y);
151             if (op[0] == ‘Q‘)
152                 printf("%d\n",get_max(x,y));
153          }
154     }
155     return 0;
156 }
时间: 2024-10-06 04:32:48

SPOJ375.QTREE树链剖分的相关文章

【学术篇】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

spoj375 树链剖分(单点更新,区间查询)

http://www.spoj.com/problems/QTREE/ 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: CHANG

SPOJ375 Query on a tree 树链剖分

SPOJ375  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

SPOJ 375 QTREE - Query on a tree(树链剖分)

题目链接:http://www.spoj.com/problems/QTREE/en/ 题意:  一棵树 n 个节点,每条边上有权值,同时有两个操作: (1)更改操作:CHANGE i ti(把第 i 条边上的权值改为 ti). (2)查询操作:QUERY a b(查询 a 到 b 的路径上权值最大的边的权值). 思路(树链剖分): 看到这种区间查询的题想要用数据结构优化,提高时间效率一般会想到线段树.可是这次操作的对象并不是一组序列, 无法直接使用线段树.这时,我们可以做些转化:对树作树链剖分

SPOJ - QTREE 375 Query on a tree 树链剖分+线段树

操作1:修改第k条边权. 操作2:询问两点间最大边权. 树链剖分,然后线段树维护最大值 #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #inclu

SPOJ QTREE Query on a tree ——树链剖分 线段树

[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 20005 int T,n,fr[maxn],h[maxn],to[maxn],ne[maxn]

spoj 375 QTREE - Query on a tree 树链剖分

题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set&g

SPOJ 375 QTREE系列-Query on a tree (树链剖分)

题目地址:SPOJ 375 树链剖分第一发! 果然是个貌似很高级的数据结构,其实就是把树的边从树形结构转化成了线性结构,从而可以用线段树或树状数组之类的数据结构进行快速维护.从而将时间缩到n*log(2*n). 这题用的线段树维护的. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #incl