LOJ10138
ZJOI 2008 树上的统计
一树上有 n 个节点,编号分别为 1 到 n,每个节点都有一个权值 w。我们将以下面的形式来要求你对这棵树完成一些操作:
CHANGE u t
:把节点 u 权值改为t;QMAX u v
:询问点 u 到点 v 路径上的节点的最大权值;QSUM u v
:询问点 u 到点 v 路径上的节点的权值和。
注意:从点 u 到点 v 路径上的节点包括 u 和 v 本身。
输入格式
第一行为一个数 n,表示节点个数;
接下来 n-1 行,每行两个整数 a,b,表示节点 a与节点 b 之间有一条边相连;
接下来 n 行,每行一个整数,第 i 行的整数 wi 表示节点i 的权值;
接下来一行,为一个整数 q ,表示操作总数;
接下来 q 行,每行一个操作,以 CHANGE u t
或 QMAX u v
或 QSUM u v
的形式给出。
输出格式
对于每个 QMAX
或 QSUM
的操作,每行输出一个整数表示要求的结果。
样例
样例输入
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
样例输出
4
1
2
2
10
6
5
6
5
16
数据范围与提示
对于 100% 的数据,有1≤n≤3×10^4,0≤q≤2×10^5。中途操作中保证每个节点的权值 w 在 −30000 至 30000 之间。
_______________________________________________________________________________________
很简单的树剖,好久没有写了,第一次写的不知道哪里错了,还是写了第二次!
_______________________________________________________________________________________
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll maxn=30020; 5 ll n,m; 6 struct edge 7 { 8 ll u,v,nxt; 9 }e[maxn<<1]; 10 ll head[maxn],js; 11 void addage(ll u,ll v) 12 { 13 e[++js].u=u;e[js].v=v; 14 e[js].nxt=head[u];head[u]=js; 15 } 16 ll w[maxn]; 17 ll dep[maxn],fat[maxn],siz[maxn],son[maxn]; 18 void dfs(ll u,ll fa) 19 { 20 dep[u]=dep[fa]+1; 21 fat[u]=fa; 22 siz[u]=1; 23 for(ll i=head[u];i;i=e[i].nxt) 24 { 25 ll v=e[i].v; 26 if(v==fa)continue; 27 dfs(v,u); 28 siz[u]+=siz[v]; 29 if(!son[u] || siz[son[u]]<siz[v])son[u]=v; 30 } 31 } 32 ll pos[maxn],top[maxn],fos[maxn],p; 33 void getpos(ll u,ll fa) 34 { 35 top[u]=fa; 36 pos[u]=++p; 37 fos[p]=u; 38 if(!son[u])return ; 39 getpos(son[u],fa); 40 for(ll i=head[u];i;i=e[i].nxt) 41 { 42 ll v=e[i].v; 43 if(v!=son[u] && v!=fat[u])getpos(v,v); 44 } 45 } 46 ll MAX,SUM; 47 ll _sum[maxn<<2],_max[maxn<<2]; 48 void update(ll cur) 49 { 50 _sum[cur]=_sum[cur<<1]+_sum[cur<<1|1]; 51 _max[cur]=max(_max[cur<<1],_max[cur<<1|1]); 52 } 53 void build(ll cur,ll l,ll r) 54 { 55 if(l==r) 56 { 57 _sum[cur]=_max[cur]=w[fos[l]]; 58 return ; 59 } 60 ll mid=(l+r)>>1; 61 build(cur<<1,l,mid); 62 build(cur<<1|1,mid+1,r); 63 update(cur); 64 } 65 void query(ll cur,ll l,ll r,ll ql,ll qr) 66 { 67 if(ql<=l && r<=qr) 68 { 69 MAX=max(_max[cur],MAX); 70 SUM+=_sum[cur]; 71 return ; 72 } 73 ll mid=(l+r)>>1; 74 if(ql<=mid)query(cur<<1,l,mid,ql,qr); 75 if(qr>mid)query(cur<<1|1,mid+1,r,ql,qr); 76 } 77 void ask(ll u,ll v) 78 { 79 ll tpu=top[u],tpv=top[v]; 80 while(tpu!=tpv) 81 { 82 if(dep[tpu]<dep[tpv]) 83 { 84 swap(u,v);swap(tpu,tpv); 85 } 86 query(1,1,n,pos[tpu],pos[u]); 87 u=fat[tpu];tpu=top[u]; 88 } 89 if(dep[u]>dep[v])swap(u,v); 90 query(1,1,n,pos[u],pos[v]); 91 } 92 void change(ll cur,ll l,ll r,ll p,ll x) 93 { 94 if(l==r) 95 { 96 _max[cur]=_sum[cur]=x; 97 return ; 98 } 99 ll mid=(l+r)>>1; 100 if(p<=mid)change(cur<<1,l,mid,p,x); 101 else change(cur<<1|1,mid+1,r,p,x); 102 update(cur); 103 } 104 int main() 105 { 106 scanf("%lld",&n); 107 for(ll i=1,u,v;i<n;++i) 108 { 109 scanf("%lld%lld",&u,&v); 110 addage(u,v);addage(v,u); 111 } 112 for(int i=1;i<=n;++i)scanf("%lld",w+i); 113 scanf("%lld",&m); 114 dfs(1,0); 115 getpos(1,1); 116 build(1,1,n); 117 char s[10]; 118 ll u,v; 119 while(m--) 120 { 121 scanf("%s%lld%lld",s,&u,&v); 122 if(s[1]=='H')change(1,1,n,pos[u],v); 123 else 124 { 125 MAX=-0x7fffffff,SUM=0; 126 ask(u,v); 127 printf("%lld\n",s[1]=='M'?MAX:SUM); 128 } 129 } 130 return 0; 131 }