LOJ10138

ZJOI 2008 树上的统计

一树上有 n 个节点,编号分别为 1 到 n,每个节点都有一个权值 w。我们将以下面的形式来要求你对这棵树完成一些操作:

  1. CHANGE u t :把节点 u 权值改为t;
  2. QMAX u v :询问点 u 到点 v 路径上的节点的最大权值;
  3. 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% 的数据,有1n3×10^4,0q2×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 }
View Code

 

posted on 2019-02-28 14:20  gryzy  阅读(140)  评论(0编辑  收藏  举报

导航