zoukankan      html  css  js  c++  java
  • 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
    ",s[1]=='M'?MAX:SUM);
    128         }
    129     }
    130     return 0;
    131 }
    View Code
  • 相关阅读:
    Turn the corner
    全排列的递归算法
    全排列的递归算法
    二分   三分搜索
    二分   三分搜索
    理解 Linux 的硬链接与软链接
    一个 Linux 上分析死锁的简单方法
    char能表示(-128~127)
    UNIX网络编程——ioctl 函数的用法详解
    UNIX网络编程——原始套接字(dos攻击)
  • 原文地址:https://www.cnblogs.com/gryzy/p/10450106.html
Copyright © 2011-2022 走看看