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
第一道樹剖 講解蠻好的:http://m.blog.csdn.net/article/details?id=52330316
#include <cstdio>#include <iostream>#include <cstring>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int maxn = 20010;char s[20];int fa[maxn],dep[maxn],siz[maxn],son[maxn];int n,a,b,c,tot,head[maxn],cnt,in[maxn];int top[maxn],w[maxn],totw,tmp[maxn],getin[maxn];struct node{ int u,v,w,num; int next;}edges[maxn*4];struct stus{ int maxal;}tree[maxn*8];void add(int u,int v,int w,int i){ edges[tot].num = i;edges[tot].v=v;edges[tot].w = w;edges[tot].next = head[u];head[u] = tot++; edges[tot].num = i;edges[tot].v = u;edges[tot].w = w;edges[tot].next = head[v];head[v] = tot++;}void init(){ scanf("%d",&n); tot = 0; memset(head,-1,sizeof(head)); for(int i = 1 ; i < n ;i++){ scanf("%d%d%d",&a,&b,&c); add(a,b,c,i); } for(int i = 1; i <= n ; i++) top[i] = i;}//fa、dep、siz、son//siz[v]表示以v為根的子樹的節點數//dep[v]表示v的深度(根深度為1)//fa[v]表示v的父親,//son[v]表示與v在同一重鏈上的v的兒子節點(姑且稱為重兒子)void dfs1(int now,int root,int h){ siz[now] = 1; dep[now] = h; fa[now] = root; int ans = -1; for(int k = head[now] ; k != -1 ;k = edges[k].next){ if(edges[k].v == root) continue; dfs1(edges[k].v,now,h+1); siz[now] += siz[edges[k].v]; if(siz[edges[k].v] > ans){ ans = siz[edges[k].v]; son[now] = edges[k].v; } }}//top[v]表示v所在的重鏈的頂端節點//w[v]表示v與其父親節點的連邊在線段樹中的位置void dfs2(int now,int root){ top[son[now]] = top[now]; if(son[now] != -1){ w[son[now]] = ++totw; dfs2(son[now],now); } else return; for(int k = head[now] ; k!= -1; k = edges[k].next){ if(edges[k].v == root) continue; if(son[now] == edges[k].v){ tmp[w[edges[k].v]] = edges[k].w; in[edges[k].num] = w[edges[k].v]; continue; } w[edges[k].v] = ++totw; tmp[totw] = edges[k].w; in[edges[k].num] = totw; dfs2(edges[k].v,now); }}void build(int l,int r,int rt){ if(l == r){ tree[rt].maxal = tmp[++cnt]; //in[getin[cnt]] = rt; // printf("tree[%d] = %d",rt,tree[rt].maxal); return; } int m = (l+r)>>1; build(lson); build(rson); tree[rt].maxal = max(tree[rt<<1].maxal,tree[rt<<1|1].maxal); //printf("tree[%d] = %d/n",rt,tree[rt].maxal);}int qurry(int l,int r,int rt,int ql,int qr){ if(ql <= l && qr >= r){ // printf("tree[%d] = %d/n",rt,tree[rt].maxal); return tree[rt].maxal; } int m = (l+r) >>1,ansnow = 0; //printf("ql = %d m = %d/n",ql,m); if(ql <= m) ansnow = max(ansnow,qurry(lson,ql,qr)); // printf("ansnow = %d/n",ansnow); if(qr > m) ansnow = max(ansnow,qurry(rson,ql,qr)); // printf("ansnow = %d/n",ansnow); return ansnow;}void sov(){ memset(son,-1,sizeof(son)); dfs1(1,-1,1); fa[1] = 1; totw = 0; top[1] = 1; dfs2(1,-1); w[1] = 0;// for(int i = 1;i <= n ; i++){// printf("node = %d top = %d son = %d w = %d dep = %d fa = %d/n",i,top[i],son[i],w[i],dep[i],fa[i]);// }// for(int i = 1; i <= totw; i++)// printf("getin[%d] = %d/n",i,getin[i]); cnt = 0; build(1,totw,1);// for(int i = 1; i <= n-1; i++)// printf("in[%d] = %d/n",i,in[i]);}void update(int l,int r,int rt,int pos,int b){ if(l == r ){ if(l == pos){ tree[rt].maxal = b; //printf("di tree[%d] = %d/n",pos,tree[pos].maxal); } // printf("rt tree[%d] = %d/n",l,rt); return; } int m = (l+r)>>1; if(m >= pos) update(lson,pos,b); if(m < pos) update(rson,pos,b); tree[rt].maxal = max(tree[rt<<1].maxal,tree[rt<<1|1].maxal); //printf("tree[%d] = %d/n",rt,tree[rt].maxal);}int cfind(int u,int v){ int tp1 = top[u],tp2 = top[v] ; // printf("tp1 = top[%d] = %d tp2 = top[%d] == %d/n",u,top[u],v,top[v]); int ans = 0; while(tp1 != tp2){ if(dep[tp1] < dep[tp2]){ swap(tp1,tp2); swap(u,v); } ans = max(ans,qurry(1,totw,1,w[tp1],w[u])); u = fa[tp1]; tp1 = top[u]; } if(u == v) return ans; if(dep[u] > dep[v]) swap(u,v); // printf("w[%d]+1 = %d w[%d] = %d/n",u,w[u]+1,v,w[v]); ans = max(ans,qurry(1,totw,1,w[u]+1,w[v])); return ans;}void cinqurry(){ while(1){ scanf("%s",s); if(s[0] == 'D') break; scanf("%d%d",&a,&b); if (s[0] == 'Q'){ printf("%d/n",cfind(a,b)); } else{ //單點修改 update(1,totw,1,in[a],b); } }}int main(){ int t; scanf("%d",&t); for(int ca = 1; ca <= t ;ca++){ init(); sov(); cinqurry(); } return 0;}/*1141 4 104 8 604 9 204 10 509 13 3013 14 401 2 902 5 1302 6 1006 12 1206 11 1101 3 703 7 80QUERY 1 2CHANGE 7 300QUERY 1 2DONE*/新聞熱點
疑難解答