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
  • 相关阅读:
    关于哈希表的一些资料
    ACM题目推荐(刘汝佳书上出现的一些题目)
    搜索引擎技术文章
    计算机体系结构文章摘选
    正则表达式语法
    三维地形显示
    无砝码天平3次称出12个小球中质量异常球问题
    关于char, wchar_t, TCHAR, _T(),L,宏 _T、TEXT,_TEXT(转)
    vcf文件分解
    Oracle 创建自动增加主键的表
  • 原文地址:https://www.cnblogs.com/gryzy/p/10454857.html
Copyright © 2011-2022 走看看