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==y) return ans; if (dep[x]>dep[y]) swap(x,y); return max(ans,ask(1,n,id[x]+1,id[y],1));
以前应该是错了。
代码:
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int M=100009; 5 int n,cnt,t,p[M],hea[M],size[M],v[M],a[M],b[M],c[M],nex[M],dep[M],top[M],id[M],tree[M<<2]; 6 char s[M]; bool vis[M]; 7 8 int read() 9 { 10 int x=0; bool f=0; char ch=getchar(); 11 while (ch<'0' || ch>'9') { if (ch=='-') f=1; ch=getchar(); } 12 while (ch>='0' && ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar(); 13 return f?-x:x; 14 } 15 16 void add(int x,int y) { v[++cnt]=y,nex[cnt]=hea[x],hea[x]=cnt; } 17 18 void dfs1(int x,int fa,int h) 19 { 20 size[x]=1,dep[x]=h,p[x]=fa; 21 for (int i=hea[x],y;i;i=nex[i]) 22 if ((y=v[i])^fa) dfs1(y,x,h+1),size[x]+=size[y]; 23 } 24 25 void dfs2(int x,int chain) 26 { 27 int i,k=0,y; 28 id[x]=++t,top[x]=chain; 29 for (i=hea[x];i;i=nex[i]) 30 if (size[y=v[i]]>size[k] && y^p[x]) k=y; 31 if (!k) return; dfs2(k,chain); 32 for (i=hea[x];i;i=nex[i]) 33 if ((y=v[i])^p[x] && k^y) dfs2(y,y); 34 } 35 36 void push_up(int k) { tree[k]=max(tree[k<<1],tree[k<<1|1]); } 37 38 void change(int L,int R,int x,int val,int cur) 39 { 40 if (L==R) { tree[cur]=val; return; } 41 int mid=L+R>>1; 42 if (x>mid) change(mid+1,R,x,val,cur<<1|1); 43 else change(L,mid,x,val,cur<<1); 44 push_up(cur); 45 } 46 47 int ask(int L,int R,int l,int r,int cur) 48 { 49 if (l<=L && R<=r) return tree[cur]; 50 int mid=L+R>>1; 51 if (r<=mid) return ask(L,mid,l,r,cur<<1); 52 else if (l>mid) return ask(mid+1,R,l,r,cur<<1|1); 53 else return max(ask(L,mid,l,mid,cur<<1),ask(mid+1,R,mid+1,r,cur<<1|1)); 54 } 55 56 int qry(int x,int y) 57 { 58 int ans=-10000000; 59 for (;top[x]^top[y];x=p[top[x]]) 60 { 61 if (dep[top[x]]<dep[top[y]]) swap(x,y); 62 ans=max(ans,ask(1,n,id[top[x]],id[x],1)); 63 } 64 if (x==y) return ans; 65 if (dep[x]>dep[y]) swap(x,y); 66 return max(ans,ask(1,n,id[x]+1,id[y],1)); 67 } 68 69 int main() 70 { 71 for (int T=read(),i;T;--T) 72 { 73 n=read(),cnt=t=0; 74 for (i=0;i<=n;++i) hea[i]=0; 75 for (i=1;i<n;++i) 76 { 77 a[i]=read(),b[i]=read(),c[i]=read(); 78 add(a[i],b[i]),add(b[i],a[i]); 79 } 80 dfs1(1,1,1),dfs2(1,1); 81 for (i=1;i<n;++i) 82 { 83 if (dep[a[i]]<dep[b[i]]) swap(a[i],b[i]); 84 change(1,n,id[a[i]],c[i],1); 85 } 86 for (;;) 87 { 88 scanf("%s",s); 89 if (s[0]=='D') break; 90 int x=read(),y=read(); 91 if (s[0]=='C') change(1,n,id[a[x]],y,1); 92 if (s[0]=='Q') printf("%d\n",qry(x,y)); 93 } 94 } 95 return 0; 96 }
我一直在繁华的苍凉中徘徊着,用一颗OI的心寻找着生命和宇宙的美妙与玄奥。