SPOJ QTREE - Query on a tree
阿新 • • 發佈:2017-08-24
deep c++ ble else pac wap name cas for each
QTREE - Query on a tree
#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
題意:給一棵樹,邊上有權值,多組詢問,問任意兩個路勁之間的最大邊權,修改某一條邊的權值。
分析:
線段樹已經爐火純青了,重新標號後,可以build操作,但是想著update更方便,也只是O(nlogn),差不了多少。
點權會容易操作的多,但是這裏是邊權,我就將線段樹底層第一個點至為 -inf,然後按照順序加上邊的權值,邊權就變成線段樹裏面的點權了。
#include <bits/stdc++.h> using namespace std; const int maxn=10005; vector <pair<int,int> > g[maxn]; int num; const int inf=1<<29; int id[maxn],deep[maxn],siz[maxn],son[maxn],fa[maxn]; int val[maxn],top[maxn]; struct Edge { int x,y,val; void read() { scanf("%d %d %d",&x,&y,&val); g[x].push_back(make_pair(y,val)); g[y].push_back(make_pair(x,val)); } }edges[maxn+20]; void dfs1(int u,int father,int d,int va) { deep[u]=d; siz[u]=1; son[u]=0; fa[u]=father; val[u] = va; for(int i=0;i<(int)g[u].size();i++) { int v=g[u][i].first; if(v==father) continue; dfs1(v,u,d+1,g[u][i].second); siz[u]+=siz[v]; if(siz[son[u]]<siz[v]) son[u]=v; } } void dfs2(int u,int tp) { top[u]=tp; id[u]=++num; if(son[u]) dfs2(son[u],tp); for(int i=0;i<(int)g[u].size();i++) { int v=g[u][i].first; if(v==fa[u]||v==son[u]) continue; dfs2(v,v); } } int qL,qR; int p,v; int _max; int n; struct IntervalTree { int maxv[maxn*4]; void build(int o,int L,int R) { int M = L + (R-L)/2; if(L==R) maxv[o] = val[L]; else { build(o*2,L,M); build(o*2+1,M+1,R); maxv[o] = max(maxv[o*2],maxv[o*2+1]); } } void update(int o,int L,int R) { int M = L + (R-L)/2; if(L==R) maxv[o] = v; else { if(p<=M) update(o*2,L,M); else update(o*2+1,M+1,R); maxv[o] = max(maxv[o*2],maxv[o*2+1]); } } int qurey(int o,int L,int R) { int M = L + (R-L)/2, ans = -inf; if(qL<=L&&R<=qR) return maxv[o]; if(qL<=M) ans = max(ans,qurey(o*2,L,M)); if(M<qR) ans = max(ans,qurey(o*2+1,M+1,R)); return ans; } }sol; int yougth(int u,int v) { int f1 = top[u],f2 = top[v]; int ret = -inf; while(f1!=f2) { if(deep[f1]<deep[f2]) { swap(u,v); swap(f1,f2); } qL = id[f1],qR = id[u],_max = -inf; _max = max(_max,sol.qurey(1,1,n)); ret = max(ret,_max); u = fa[f1]; f1 = top[u]; } if(u==v) return ret; if(deep[u]>deep[v]) swap(u,v); qL = id[son[u]],qR=id[v],_max = -inf; _max = max(_max,sol.qurey(1,1,n)); ret = max(ret,_max); return ret; } int main(int argc, char const *argv[]) { // freopen("in.txt","r",stdin); int t; scanf("%d",&t); while(t--) { scanf("%d",&n); for (int i = 0; i < maxn; ++i) g[i].clear(); for (int i = 1; i < n; ++i) edges[i].read(); num = 0; dfs1(1,0,1,-inf); dfs2(1,1); for(int i=1; i <=n; i++) { p = id[i]; v = val[i]; sol.update(1,1,n); } char cmd[20]; while(scanf("%s",cmd),strcmp(cmd,"DONE")!=0) { if(strcmp(cmd,"QUERY")==0) { int u,v; scanf("%d%d",&u,&v); printf("%d\n",yougth(u,v)); } else { int a,b; scanf("%d%d",&a,&b); int t = fa[edges[a].y] == edges[a].x ? edges[a].y : edges[a].x; p = id[t],v = b; sol.update(1,1,n); } } } return 0; }
SPOJ QTREE - Query on a tree