zoukankan      html  css  js  c++  java
  • LOJ2125

    LOJ2125 树上操作

    题目描述

    有一棵点数为 N 的树,以点 1 为根,且树有点权。然后有 M 个操作,分为三种:

    1. 把某个节点 x 的点权增加 aa 。
    2. 把某个节点 x 为根的子树中所有点的点权都增加 a 。
    3. 询问某个节点 x 到根的路径中所有点的点权和。

    输入格式

    第一行包含两个整数 N, M。表示点数和操作数。
    接下来一行 N 个整数,表示树中节点的初始权值。
    接下来 N-1 行每行两个正整数 fr,to , 表示该树中存在一条边(fr,to) 。
    再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类(1-3) ,之后接这个操作的参数(x 或者 x a) 。

    输出格式

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

    样例

    样例输入

    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3

    样例输出

    6
    9
    13

    数据范围与提示

    对于 100% 的数据, N,M10^5 ,且所有输入数据的绝对值都不会超过 10^6 。

    ________________________________________________________________________________________

    简单的树链剖分,而且树上的查询也比较简单,只是从某个节点到根的权值和。需要注意的如何处理子树的权值修改。这个就是用到了DFS序。需要记录每个点为跟的子树在线段树中左右边界。

    ________________________________________________________________________________________

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const ll maxn=1e5+10;
      5 ll n,m;
      6 ll w[maxn];
      7 struct edge
      8 {
      9     int u,v,nxt;
     10 }e[maxn<<1];
     11 ll head[maxn],js;
     12 void addage(ll u,ll v)
     13 {
     14     e[++js].u=u;e[js].v=v;
     15     e[js].nxt=head[u];head[u]=js;
     16 }
     17 ll dep[maxn],siz[maxn],fat[maxn],son[maxn];
     18 void dfs(int u,int fa)
     19 {
     20     siz[u]=1;
     21     dep[u]=dep[fa]+1;
     22     fat[u]=fa;
     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 lp[maxn],rp[maxn],top[maxn],fos[maxn],p;
     33 void getpos(ll u,ll fa)
     34 {
     35     lp[u]=++p;
     36     fos[p]=u;
     37     top[u]=fa;
     38     if(!son[u])
     39     {
     40         rp[u]=p;
     41         return;
     42     }
     43     getpos(son[u],fa);
     44     for(ll i=head[u];i;i=e[i].nxt)
     45     {
     46         ll v=e[i].v;
     47         if(v!=fat[u] && v!=son[u])getpos(v,v);
     48     }
     49     rp[u]=p;
     50 }
     51 ll sum[maxn<<2],delt[maxn<<2];
     52 inline void updat(ll cur)
     53 {
     54     sum[cur]=sum[cur<<1]+sum[cur<<1|1];
     55 }
     56 void build(ll cur,ll l,ll r)
     57 {
     58     if(l==r)
     59     {
     60         sum[cur]=w[fos[l]];
     61         return;
     62     }
     63     ll mid=(l+r)>>1;
     64     build(cur<<1,l,mid);
     65     build(cur<<1|1,mid+1,r);
     66     updat(cur);
     67 }
     68 void down(ll cur,ll l,ll r)
     69 {
     70     ll mid=(l+r)>>1;
     71     delt[cur<<1]+=delt[cur];
     72     delt[cur<<1|1]+=delt[cur];
     73     sum[cur<<1]+=delt[cur]*(mid-l+1);
     74     sum[cur<<1|1]+=delt[cur]*(r-mid);
     75     delt[cur]=0;
     76 }
     77 void add(ll cur,ll l,ll r,ll p,ll x)
     78 {
     79     if(l==r)
     80     {
     81         sum[cur]+=x;
     82         return ;
     83     }
     84     ll mid=(l+r)>>1;
     85     if(delt[cur])down(cur,l,r);
     86     if(p<=mid)add(cur<<1,l,mid,p,x);
     87     else add(cur<<1|1,mid+1,r,p,x);
     88     updat(cur);
     89 }
     90 void add_(ll cur,ll l,ll r,ll ql,ll qr,ll x)
     91 {
     92     if(ql<=l && r<=qr)
     93     {
     94         sum[cur]+=(r-l+1)*x;
     95         delt[cur]+=x;
     96         return ;
     97     }
     98     down(cur,l,r);
     99     ll mid=(l+r)>>1;
    100     if(ql<=mid)add_(cur<<1,l,mid,ql,qr,x);
    101     if(mid<qr)add_(cur<<1|1,mid+1,r,ql,qr,x);
    102     updat(cur);
    103 }
    104 ll query(ll cur,ll l,ll r,ll ql,ll qr)
    105 {
    106     if(ql<=l && r<=qr)return sum[cur];
    107     ll ans=0,mid=(l+r)>>1;
    108     if(delt[cur])down(cur,l,r);
    109     if(ql<=mid)ans+=query(cur<<1,l,mid,ql,qr);
    110     if(mid<qr)ans+=query(cur<<1|1,mid+1,r,ql,qr);
    111     return ans;
    112 }
    113 ll ask(ll x)
    114 {
    115     ll ans=0;
    116     while(x)
    117     {
    118         ll tpx=top[x];
    119         ans+=query(1,1,n,lp[tpx],lp[x]);
    120         x=fat[tpx];tpx=top[x];
    121     }
    122     return ans;
    123 }
    124 int main()
    125 {
    126     scanf("%lld%lld",&n,&m);
    127     for(int i=1;i<=n;++i)scanf("%lld",w+i);
    128     for(ll u,v,i=1;i<n;++i)
    129     {
    130         scanf("%lld%lld",&u,&v);
    131         addage(u,v);addage(v,u);
    132     }
    133     dfs(1,0);
    134     getpos(1,1);
    135     build(1,1,n);
    136     while(m--)
    137     {
    138         ll x,a,op;
    139         scanf("%lld%lld",&op,&x);
    140         if(op!=3)scanf("%lld",&a);
    141         if(op==1)add(1,1,n,lp[x],a);
    142         else if(op==2)add_(1,1,n,lp[x],rp[x],a);
    143         else printf("%lld
    ",ask(x));
    144     }
    145     return 0;
    146 }
    View Code
  • 相关阅读:
    WHERE col1=val1 AND col2=val2;index exists on col1 and col2, the appropriate rows can be fetched directly
    MySQL 交集 实现方法
    MBProgressHUD的使用
    Xcode4 使用 Organizer 分析 Crash logs(转)
    SimpleXML 使用详细例子
    PHP的XML Parser(转)
    iPhone,iPhone4,iPad程序启动画面的总结 (转)
    Pop3得到的Email 信件格式介绍
    yii总结
    隐藏Tabbar的一些方法
  • 原文地址:https://www.cnblogs.com/gryzy/p/10454857.html
Copyright © 2011-2022 走看看