spoj375 QTREE - 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 a, b 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我也不知道这个oj怎么注册,大概找了一份标程拍了一上午,应该没问题。就是一个树剖裸题,树单点修改和查询(u,v)路径最大值。
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 const int N =  100000 + 11 , inf = 1 << 30;
  6 using namespace std ;
  7 int n, head[N] , tot = 0,sum;
  8 struct id
  9 {
 10     int fro,nxt,to,val;
 11 } E[N<<1];
 12 void add( int u , int v , int val )
 13 {
 14     E[++tot] = (id){u,head[u],v,val};head[u] = tot;
 15     E[tot+n-1] = (id){v,head[v],u,val};head[v] = tot+n-1;
 16 }
 17 struct Node
 18 {
 19     int deep,fa,size,zson,top,pos;
 20 } node[N];
 21 struct seg
 22 {
 23     int l,r,val;
 24 }T[N<<2]; int cnt;
 25
 26 void dfs1( int u, int pre, int dep )
 27 {
 28     node[u] = (Node){dep,pre,1,-1};
 29     for(int i = head[u];~i;i = E[i].nxt)
 30     {
 31         int v = E[i].to ;
 32         if( v == pre ) continue;
 33         dfs1(v,u,dep+1);
 34         node[u].size += node[v].size;
 35         if(node[u].zson == -1 || node[v].size > node[node[u].zson].size) node[u].zson = v;
 36     }
 37
 38 }
 39 void dfs2(int u ,int p)
 40 {
 41     node[u].top = p; node[u].pos = ++sum;
 42     if(~node[u].zson)dfs2(node[u].zson,node[u].top);
 43     for(int i = head[u];~i;i = E[i].nxt)
 44     {
 45         int v = E[i].to;
 46         if(v == node[u].fa || v == node[u].zson)continue;
 47         dfs2(v,v);
 48     }
 49 }
 50
 51 void Init()
 52 {
 53     scanf("%d",&n);
 54     memset(head,-1,sizeof(head));
 55     tot = 0 , sum = 0,cnt = 1;
 56     int a,b,c;
 57     for(int i = 1 ; i < n; ++i)
 58     {
 59         scanf("%d%d%d",&a,&b,&c);
 60         add(a,b,c);
 61     }
 62     dfs1(1,0,0);
 63     dfs2(1,1);
 64 }
 65
 66 void updata( int l,int r,int &num, int cp , int val )
 67 {
 68
 69     if(!num) { num = ++cnt; T[num] = (seg){0,0,-inf};}
 70     if( l == r ){ T[num].val = val ; return ;}
 71     int mid =  ( l + r ) >> 1 ;
 72     if(mid >= cp)
 73     {
 74         updata(l,mid,T[num].l,cp,val) ;
 75         T[num].val = T[T[num].l].val;
 76         if(T[num].r) T[num].val = max(T[num].val,T[T[num].r].val);
 77     }
 78     else
 79     {
 80         updata(mid+1,r,T[num].r,cp,val) ;
 81         T[num].val = T[T[num].r].val;
 82         if(T[num].l) T[num].val = max(T[num].val,T[T[num].l].val);
 83     }
 84
 85 }
 86
 87 int query( int l , int r, int num , int L , int R )
 88 {
 89     if(l == L && r == R) return T[num].val;
 90     int mid = (l + r) >> 1;
 91     if(mid >= R)return query(l,mid,T[num].l,L,R);
 92     else if(L > mid) return query(mid+1,r,T[num].r,L,R);
 93     else return max(query(l,mid,T[num].l,L,mid),query(mid+1,r,T[num].r,mid+1,R));
 94 }
 95
 96 int lca(int x,int y)
 97 {
 98     int ans = -inf;
 99     while(node[x].top != node[y].top)
100     {
101         if(node[node[x].top].deep < node[node[y].top].deep) swap(x,y);
102         ans = max(ans , query(1,n,1,node[node[x].top].pos,node[x].pos));
103         x = node[node[x].top].fa;
104     }
105     if( node[x].deep > node[y].deep ) swap(x,y);
106     if(x != y)
107         ans = max(ans,query(1,n,1,node[x].pos+1,node[y].pos));
108     return ans;
109 }
110
111
112 void Solve()
113 {
114     char ch[10];
115     int a , b; T[1].val = -inf;T[1] = (seg){0,0,-inf};
116     for(int i = 1; i < n ; ++i)
117     {
118         if(node[E[i].fro].deep > node[E[i].to].deep) swap(E[i].fro,E[i].to);
119         int now = 1;
120         updata(1,n,now,node[E[i].to].pos,E[i].val);
121     }
122     while(~scanf("%s",ch)&&ch[0]!=‘D‘)
123     {
124         if(ch[0] == ‘Q‘)
125         {
126             scanf("%d%d",&a,&b);
127             printf("%d\n",lca(a,b));
128         }
129         else if(ch[0] == ‘C‘)
130         {
131             scanf("%d%d",&a,&b);
132             int now = 1 ;
133             updata(1,n,now,node[E[a].to].pos,b);
134         }
135
136     }
137 }
138
139 int main( )
140 {
141     int t;
142     scanf("%d",&t);
143     while(t--)
144     {
145         Init();
146         Solve();
147     }
148     return 0;
149 }
时间: 2024-10-12 16:28:00

spoj375 QTREE - Query on a tree的相关文章

QTREE - Query on a tree

QTREE - Query on a tree 题目链接:http://www.spoj.com/problems/QTREE/ 参考博客:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html 树链剖分入门题 代码如下(附注解): 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define lson (x<<1) 5 #d

SP375 QTREE - Query on a tree (树剖)

题目 SP375 QTREE - Query on a tree 解析 也就是个蓝题,因为比较长 树剖裸题(基本上),单点修改,链上查询. 可以看到这个题然我们对边进行操作,我们的树剖是对节点进行操作的,所以我们考虑把边权转移到点权上. 发现我们节点的点权是连向它的边的边权,所以我们要修改或查询边权的话,我们修改或查询的实际上是其连向点的点权, 假设我们要修改1-4之间的这两条边 我们修改的实际上就是这两个点 所以我们链上修改或查询的时候,不要修改或查询深度较浅的节点. 然后这是SPOJ上的题,

SP375 QTREE - Query on a tree

SP375 QTREE - Query on a tree 我是借这道题来说说如何从c++改到c的 1.我怕麻烦,所以把结构体拆了(忍痛割爱我封装的线段树) 2.max.swap函数进行了手写 max: ll llmax(ll x,ll y){return x>y?x:y;} swap: x^=y^=x^=y emm...这的确是一个神奇的swap,不用函数 至于为什么是对的用人类智慧法即可 c++代码:(线段树封装) #include<bits/stdc++.h> using name

SPOJ QTREE - Query on a tree

Description 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 tior QUERY

SPOJ QTREE Query on a tree --树链剖分

题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. 询问的时候,在从u找到v的过程中顺便查询到此为止的最大值即可. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath&

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 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 - QTREE Query on a tree题解

题目大意: 一棵树,有边权,有两个操作:1.修改一条边的权值:2.询问两点间路径上的边的权值的最大值. 思路: 十分裸的树链剖分+线段树,无非是边权要放到深度大的一端的点上,但是有两个坑爹的地方,改了好久: 1.数组定义10000和40000会TLE,要乘10: 2.以前的树剖求解的最后是这样的: if (deep[x]>deep[y]) swap(x,y); return max(ans,MAX(1,n,id[x],id[y],1)); 但是WA了,膜拜大神后发现这样就AC了: if (x==