照着题解慢慢写。
http://bestcoder.hdu.edu.cn/blog/
有几个需要注意的地方:
1. 与父节点共边的判断,可以在dfs里面处理。
2. 区分开具体点与共轴块的区别。
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef pair<pii,int> ppi;
const int maxn=100005;
const int inf=0x3f3f3f3f;
const double log_2=log(2.0);
int T,n,m,q,f[maxn],rad[maxn],dfn,st[maxn],ed[maxn],rt[maxn],depth[maxn],left[maxn],right[maxn],edge[maxn];
vector<int> temp[maxn];
vector<ppi> G[maxn];
inline int log2(int x) {
int ret=0;
while (x) {
x>>=1;
++ret;
}
return ret-1;
}
int F(int x) {
return x==f[x]?x:f[x]=F(f[x]);
}
void U(int a,int b) {
f[F(a)]=F(b);
}
struct node {
int l,r,lazy,mmax;
void update(int val) {
mmax+=val;
lazy+=val;
}
}seg[maxn<<2];
inline void pushup(int x) {
seg[x].mmax=max(seg[x<<1].mmax,seg[x<<1|1].mmax);
}
inline void pushdown(int x) {
int lz=seg[x].lazy;
if (lz) {
seg[x].lazy=0;
seg[x<<1].update(lz);
seg[x<<1|1].update(lz);
}
}
void build(int x,int l,int r) {
seg[x].l=l,seg[x].r=r,seg[x].lazy=0;
if (l==r) {
seg[x].mmax=depth[l];
return;
}
int m=(l+r)>>1;
build(x<<1,l,m);
build(x<<1|1,m+1,r);
pushup(x);
}
void update(int x,int l,int r,int val) {
int L=seg[x].l,R=seg[x].r;
if (l<=L&&r>=R) {
seg[x].update(val);
return;
}
pushdown(x);
int m=(L+R)>>1;
if (m>=l)
update(x<<1,l,r,val);
if (m<r)
update(x<<1|1,l,r,val);
pushup(x);
}
int query(int x,int l,int r) {
int L=seg[x].l,R=seg[x].r;
if (l<=L&&r>=R)
return seg[x].mmax;
pushdown(x);
int m=(L+R)>>1,ret=-inf;
if (m>=l)
ret=max(ret,query(x<<1,l,r));
if (m<r)
ret=max(ret,query(x<<1|1,l,r));
pushup(x);
return ret;
}
void dfs(int u,int fa,int root,int d) {
rt[u]=root;
depth[st[u]=++dfn]=d;
for (int i=0;i<(int)G[u].size();++i) {
int v=G[u][i].first.first;
int t=G[u][i].first.second;
int o=G[u][i].second;
if (v==fa) {
edge[t]=1;
continue;
}
dfs(v,u,root,d+o);
left[t]=min(left[t],st[v]);
right[t]=max(right[t],ed[v]);
}
ed[u]=dfn;
}
int main()
{
while (scanf("%d%d%d",&n,&m,&q)==3) {
memset(rt,0,(n+1)*sizeof rt[0]);
memset(right,0,(n+1)*sizeof right[0]);
memset(left,0x3f,(n+1)*sizeof left[0]);
memset(edge,0,(n+1)*sizeof edge[0]);
for (int i=1;i<=n;++i) {
scanf("%d",&rad[i]);
rad[i]=log2(rad[i]);
temp[i].clear();
G[i].clear();
f[i]=i;
}
for (int i=0;i<m;++i) {
int a,u,v;
scanf("%d%d%d",&a,&u,&v);
if (a==1) {
temp[u].push_back(v);
temp[v].push_back(u);
} else
U(u,v);
}
for (int i=1;i<=n;++i)
for (int j=0;j<(int)temp[i].size();++j) {
int v=temp[i][j];
G[F(i)].push_back(ppi(pii(F(v),i),rad[i]-rad[v]));
}
dfn=0;
for (int i=1;i<=n;++i)
if (i==F(i)&&!rt[i])
dfs(i,0,i,0);
build(1,1,dfn);
printf("Case #%d:\n",++T);
while (q--) {
int a,x,y;
scanf("%d%d%d",&a,&x,&y);
y=log2(y);
int fa=F(x);
if (a==1) {
int delta=y-rad[x];
if (edge[x])
update(1,st[fa],ed[fa],-delta);
if (left[x]<=right[x])
update(1,left[x],right[x],delta);
rad[x]=y;
} else {
int res=y-query(1,st[fa],st[fa])+query(1,st[rt[fa]],ed[rt[fa]]);
printf("%.3f\n",res*log_2);
}
}
}
return 0;
}