zoukankan      html  css  js  c++  java
  • 「HAOI2015」「LuoguP3178」树上操作(树链剖分

    题目描述

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

    操作 1 :把某个节点 x 的点权增加 a 。

    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。

    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    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
    输出样例#1: 复制
    6
    9
    13

    说明

    对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不

    会超过 10^6 。

    题解

    先剖一下。

    操作1:在dfn[x]处+=a

    操作2:从dfn[x]到dfn[x]+siz[x]-1上区间+a

    操作3:往上跳的同时ans+=find(dfn[top[x]],dfn[x])

    几乎是阉割版的树剖了。

      1 /*
      2     qwerta
      3     P3178 [HAOI2015]树上操作
      4     Accepted
      5     100
      6     代码 C++,2.93KB
      7     提交时间 2018-09-11 17:00:43
      8     耗时/内存
      9     993ms, 24476KB
     10 */
     11 #include<cstdio>
     12 #include<iostream>
     13 using namespace std;
     14 #define LL long long
     15 const LL MAXN=100000+7;
     16 LL val[MAXN];
     17 struct emm{
     18     LL e,f;
     19 }b[2*MAXN];
     20 LL h[MAXN];
     21 LL tot=0;
     22 void con(LL x,LL y)
     23 {
     24     b[++tot].f=h[x];
     25     h[x]=tot;
     26     b[tot].e=y;
     27     b[++tot].f=h[y];
     28     h[y]=tot;
     29     b[tot].e=x;
     30     return;
     31 }
     32 LL d[MAXN],siz[MAXN],z[MAXN],fa[MAXN],top[MAXN];
     33 void dfs(LL x)
     34 {
     35     siz[x]=1,top[x]=x;
     36     LL mac=0,macc=-1;
     37     for(LL i=h[x];i;i=b[i].f)
     38     if(!d[b[i].e])
     39     {
     40         d[b[i].e]=d[x]+1;
     41         fa[b[i].e]=x;
     42         dfs(b[i].e);
     43         siz[x]+=siz[b[i].e];
     44         if(macc<siz[b[i].e]){mac=b[i].e,macc=siz[b[i].e];}
     45     }
     46     z[x]=mac;
     47     top[mac]=x;
     48     return;
     49 }
     50 LL q[MAXN],dfn[MAXN];
     51 void dfss(LL x)
     52 {
     53     q[++tot]=x;
     54     dfn[x]=tot;
     55     if(z[x])dfss(z[x]);
     56     for(LL i=h[x];i;i=b[i].f)
     57     if(fa[b[i].e]==x&&b[i].e!=z[x])
     58     dfss(b[i].e);
     59     return;
     60 }
     61 LL fitop(LL x)
     62 {
     63     if(top[x]==x)return x;
     64     return top[x]=fitop(top[x]);
     65 }
     66 struct ahh{
     67     LL l,r,mid;
     68     long long v,laz;
     69 }a[8*MAXN];
     70 #define lz (i<<1)
     71 #define rz ((i<<1)|1)
     72 #define amid a[i].mid
     73 void build(LL i,LL ll,LL rr)
     74 {
     75     a[i].l=ll;
     76     a[i].r=rr;
     77     if(ll==rr){a[i].v=val[q[ll]];return;}
     78     amid=(ll+rr)>>1;
     79     build(lz,ll,amid);
     80     build(rz,amid+1,rr);
     81     a[i].v=a[lz].v+a[rz].v;
     82     return;
     83 }
     84 void add(LL i,LL ll,LL rr,LL k)
     85 {
     86     if(a[i].l==ll&&a[i].r==rr){a[i].laz+=k;return;}
     87     a[i].v+=(rr-ll+1)*k;
     88     if(rr<=amid)add(lz,ll,rr,k);
     89     else if(amid+1<=ll)add(rz,ll,rr,k);
     90     else {add(lz,ll,amid,k);add(rz,amid+1,rr,k);}
     91     return;
     92 }
     93 long long ans=0;
     94 void pushtag(LL i)
     95 {
     96     if(!a[i].laz)return;
     97     a[i].v+=(a[i].r-a[i].l+1)*a[i].laz;
     98     if(a[i].l==a[i].r){a[i].laz=0;return;}
     99     a[lz].laz+=a[i].laz;
    100     a[rz].laz+=a[i].laz;
    101     a[i].laz=0;
    102     return;
    103 }
    104 void find(LL i,LL ll,LL rr)
    105 {
    106     pushtag(i);
    107     if(a[i].l==ll&&a[i].r==rr){ans+=a[i].v;return;}
    108     if(rr<=amid)find(lz,ll,rr);
    109     else if(amid+1<=ll)find(rz,ll,rr);
    110     else {find(lz,ll,amid);find(rz,amid+1,rr);}
    111     return;
    112 }
    113 LL s;
    114 int main()
    115 {
    116     //freopen("a.in","r",stdin);
    117     LL n,m;
    118     scanf("%lld%lld",&n,&m);
    119     for(LL i=1;i<=n;++i)
    120     scanf("%lld",&val[i]);
    121     for(LL i=1;i<n;++i)
    122     {
    123         LL u,v;
    124         scanf("%lld%lld",&u,&v);
    125         con(u,v);
    126     }
    127     s=1;
    128     d[s]=1;
    129     dfs(s);
    130     tot=0;
    131     dfss(s);
    132     for(LL i=1;i<=n;++i)
    133     top[i]=fitop(i);
    134     build(1,1,n);
    135     for(LL i=1;i<=m;++i)
    136     {
    137         LL opt;
    138         scanf("%lld",&opt);
    139         if(opt==1)
    140         {
    141             LL x,v;
    142             scanf("%lld%lld",&x,&v);
    143             add(1,dfn[x],dfn[x],v);
    144         }
    145         else if(opt==2)
    146         {
    147             LL x,v;
    148             scanf("%lld%lld",&x,&v);
    149             add(1,dfn[x],dfn[x]+siz[x]-1,v);
    150         }
    151         else
    152         {
    153             LL x;
    154             scanf("%lld",&x);
    155             ans=0;
    156             while(x)
    157             {
    158                 find(1,dfn[top[x]],dfn[x]);
    159                 x=fa[top[x]];
    160             }
    161             printf("%lld
    ",ans);
    162         }
    163     }
    164     return 0;
    165 }
  • 相关阅读:
    VB.NET与C# 语法区别展示
    利用 ASP.NET 的内置功能抵御 Web 攻击 (1)
    .NET 中获取调用方法名
    C# 6.0 的那些事
    .NET基础之自定义泛型
    汽车学习---汽车知识大全【all】
    Django学习---抽屉热搜榜分析【all】
    Python 系统学习梳理_【All】
    Python学习---装饰器/迭代器/生成器的学习【all】
    Java 系统学习梳理_【All】
  • 原文地址:https://www.cnblogs.com/qwerta/p/9629928.html
Copyright © 2011-2022 走看看