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

Query on a tree

Time Limit: 5000ms

Memory Limit: 262144KB

This problem will be judged on SPOJ. Original ID: QTREE
64-bit integer IO format: %lld      Java class name: Main

Prev Submit Status Statistics Discuss Next

Font Size: + -

Type:  
None

Graph Theory

2-SAT

Articulation/Bridge/Biconnected Component

Cycles/Topological Sorting/Strongly Connected Component

Shortest Path

Bellman Ford

Dijkstra/Floyd Warshall

Euler Trail/Circuit

Heavy-Light Decomposition

Minimum Spanning Tree

Stable Marriage Problem

Trees

Directed Minimum Spanning Tree

Flow/Matching

Graph Matching

Bipartite Matching

Hopcroft–Karp Bipartite Matching

Weighted Bipartite Matching/Hungarian Algorithm

Flow

Max Flow/Min Cut

Min Cost Max Flow

DFS-like

Backtracking with Pruning/Branch and Bound

Basic Recursion

IDA* Search

Parsing/Grammar

Breadth First Search/Depth First Search

Advanced Search Techniques

Binary Search/Bisection

Ternary Search

Geometry

Basic Geometry

Computational Geometry

Convex Hull

Pick‘s Theorem

Game Theory

Green Hackenbush/Colon Principle/Fusion Principle

Nim

Sprague-Grundy Number

Matrix

Gaussian Elimination

Matrix Exponentiation

Data Structures

Basic Data Structures

Binary Indexed Tree

Binary Search Tree

Hashing

Orthogonal Range Search

Range Minimum Query/Lowest Common Ancestor

Segment Tree/Interval Tree

Trie Tree

Sorting

Disjoint Set

String

Aho Corasick

Knuth-Morris-Pratt

Suffix Array/Suffix Tree

Math

Basic Math

Big Integer Arithmetic

Number Theory

Chinese Remainder Theorem

Extended Euclid

Inclusion/Exclusion

Modular Arithmetic

Combinatorics

Group Theory/Burnside‘s lemma

Counting

Probability/Expected Value

Others

Tricky

Hardest

Unusual

Brute Force

Implementation

Constructive Algorithms

Two Pointer

Bitmask

Beginner

Discrete Logarithm/Shank‘s Baby-step Giant-step Algorithm

Greedy

Divide and Conquer

Dynamic Programming

Tag it!

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
  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<cstdlib>
  4 #include<cstring>
  5 using namespace std;
  6 const int maxn = 1e4+13;
  7
  8 struct node
  9 {
 10     int l,r,Max;
 11 }f[maxn*4];
 12
 13 struct Edge
 14 {
 15     int to,next;
 16 }edge[maxn*2];
 17
 18 int e[maxn][3];
 19 int p[maxn];
 20 int top[maxn];
 21 int siz[maxn];
 22 int son[maxn];
 23 int deep[maxn];
 24 int father[maxn];
 25 int head[maxn];
 26 int num[maxn];
 27 int cont,pos;
 28
 29 void init()
 30 {
 31     cont = 0;
 32     pos = 0;
 33     memset(head,-1,sizeof(head));
 34     memset(son,-1,sizeof(son));
 35 }
 36 void add(int n1,int n2)
 37 {
 38     edge[cont].to=n2;// 指向谁
 39     edge[cont].next=head[n1];
 40     head[n1]=cont;
 41     cont++;
 42 }
 43
 44 void dfs1(int u,int pre,int d)/**fa deep,num,son**/
 45 {
 46     deep[u]=d;
 47     father[u]=pre;
 48     num[u]=1;
 49     for(int i=head[u];i!=-1;i=edge[i].next)
 50     {
 51         int v = edge[i].to;
 52         if(v!=pre)
 53         {
 54             dfs1(v,u,d+1);
 55             num[u]=num[u]+num[v];
 56             if(son[u]==-1 || num[v]>num[son[u]])
 57             son[u]=v;
 58         }
 59     }
 60 }
 61
 62 void getops(int u,int sp)
 63 {
 64     top[u]=sp;
 65     if(son[u]!=-1)
 66     {
 67         p[u]=++pos;
 68         getops(son[u],sp);
 69     }
 70     else
 71     {
 72         p[u]=++pos;
 73         return;
 74     }
 75     for(int i=head[u];i!=-1;i=edge[i].next)
 76     {
 77         int v = edge[i].to;
 78         if(v!=son[u] && v!=father[u])
 79         getops(v,v);
 80     }
 81 }
 82 void build(int l,int r,int n)
 83 {
 84     f[n].l=l;
 85     f[n].r=r;
 86     f[n].Max=0;
 87     if(l==r)return;
 88     int mid=(l+r)/2;
 89     build(l,mid,n*2);
 90     build(mid+1,r,n*2+1);
 91 }
 92 int query(int l,int r,int n)
 93 {
 94     int mid=(f[n].l+f[n].r)/2;
 95     int ans1,ans2;
 96     if(f[n].l==l && f[n].r==r) return f[n].Max;
 97     if(mid>=r) return query(l,r,n*2);
 98     else if(mid<l) return query(l,r,n*2+1);
 99     else
100     {
101         ans1=query(l,mid,n*2);
102         ans2=query(mid+1,r,n*2+1);
103         if(ans1<ans2) ans1=ans2;
104     }
105     return ans1;
106 }
107 void update(int x,int num1,int n)
108 {
109     int mid=(f[n].l+f[n].r)/2;
110     if(f[n].l == x && f[n].r == x)
111     {
112         f[n].Max=num1;
113         return;
114     }
115     if(mid>=x) update(x,num1,n*2);
116     else update(x,num1,n*2+1);
117     f[n].Max = f[n*2].Max>f[n*2+1].Max? f[n*2].Max:f[n*2+1].Max;
118 }
119 int find(int u,int v)
120 {
121     int f1 = top[u],f2 = top[v];
122     int MAX=0;
123     while(f1!=f2)
124     {
125        if(deep[f1]<deep[f2])
126        {
127            swap(f1,f2);
128            swap(u,v);
129        }
130        MAX=max(MAX,query(p[f1],p[u],1));
131        u=father[f1];
132        f1=top[u];
133     }
134     if(u==v)return MAX;
135     if(deep[u]>deep[v])swap(u,v);
136     return max(MAX,query(p[son[u]],p[v],1));
137 }
138 int main()
139 {
140     int T,n,l,r,x,num1;
141     char a[12];
142     scanf("%d",&T);
143     while(T--)
144     {
145         scanf("%d",&n);
146         init();
147         for(int i=1;i<n;i++)
148         {
149             scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
150             add(e[i][0],e[i][1]);
151             add(e[i][1],e[i][0]);
152         }
153         dfs1(1,0,0);
154         getops(1,1);
155         build(1,pos,1);
156         for(int i=1;i<n;i++)
157         {
158             if(deep[e[i][0]]>deep[e[i][1]]) swap(e[i][0],e[i][1]);
159             update(p[e[i][1]],e[i][2],1);
160         }
161         while(scanf("%s",a)>0)
162         {
163             if(a[0]==‘D‘)break;
164             if(a[0]==‘Q‘)
165             {
166                 scanf("%d%d",&l,&r);
167                 printf("%d\n",find(l,r));
168             }
169             else if(a[0]==‘C‘)
170             {
171                 scanf("%d%d",&x,&num1);
172                 update(p[e[x][1]],num1,1);
173             }
174         }
175     }
176     return 0;
177 }
时间: 2024-08-10 23:12:39

SPOJ 375. Query on a tree (树链剖分)的相关文章

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

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 Q

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 QTREE Query on a tree --树链剖分

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

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 树链剖分

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

spoj Query on a tree(树链剖分模板题)

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

SPOJ 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 tior QUERY a b : ask fo

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 f

Query on a tree 树链剖分

题意: 给你一棵树,和树上边的权值,在有q组询问a,b,问你从节点a->节点1的路径上,不小于b的最大的边的权值是多少,输出 离线维护最大值线段树即可 模板题 #include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define R