zoukankan      html  css  js  c++  java
  • bzoj4034: [HAOI2015]树上操作(树剖)

    4034: [HAOI2015]树上操作

    题目:传送门 


    题解:

       树剖裸题:

       麻烦一点的就只有子树修改(其实一点也不),因为子树编号连续啊,直接改段(记录编号最小和最大)

       开个long long 水模版

        


    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cmath>
      5 #include<algorithm>
      6 using namespace std;
      7 typedef long long LL;
      8 struct node
      9 {
     10     int x,y,next;
     11 }a[210000];int len,last[110000];
     12 void ins(int x,int y)
     13 {
     14     len++;a[len].x=x;a[len].y=y;
     15     a[len].next=last[x];last[x]=len;
     16 }
     17 struct trnode
     18 {
     19     int l,r,lc,rc;LL c,lz;
     20     trnode(){lz=0;}
     21 }tr[210000];int trlen;
     22 void update(int now)
     23 {
     24     if(tr[now].lz!=0)
     25     {
     26         int lc=tr[now].lc,rc=tr[now].rc;
     27         if(lc!=-1)tr[lc].c+=LL(tr[lc].r-tr[lc].l+1)*tr[now].lz,tr[lc].lz+=tr[now].lz;
     28         if(rc!=-1)tr[rc].c+=LL(tr[rc].r-tr[rc].l+1)*tr[now].lz,tr[rc].lz+=tr[now].lz;
     29         tr[now].lz=0;
     30     }
     31 }
     32 void bt(int l,int r)
     33 {
     34     int now=++trlen;
     35     tr[now].l=l;tr[now].r=r;tr[now].c=0;
     36     tr[now].lc=tr[now].rc=-1;
     37     if(l<r)
     38     {
     39         int mid=(l+r)/2;
     40         tr[now].lc=trlen+1;bt(l,mid);
     41         tr[now].rc=trlen+1;bt(mid+1,r);
     42     }
     43 }
     44 void change(int now,int l,int r,LL c)
     45 {
     46     if(tr[now].l==l && r==tr[now].r){tr[now].c+=LL(r-l+1)*c;tr[now].lz+=c;return ;}
     47     int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
     48     update(now);
     49     if(r<=mid)change(lc,l,r,c);
     50     else if(mid+1<=l)change(rc,l,r,c);
     51     else change(lc,l,mid,c),change(rc,mid+1,r,c);
     52     tr[now].c=tr[lc].c+tr[rc].c;
     53 }
     54 LL getsum(int now,int l,int r)
     55 {
     56     if(tr[now].l==l && r==tr[now].r)return tr[now].c;
     57     int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
     58     update(now);
     59     if(r<=mid)return getsum(lc,l,r);
     60     else if(mid+1<=l)return getsum(rc,l,r);
     61     return getsum(lc,l,mid)+getsum(rc,mid+1,r);
     62 }
     63 int n,m,fa[110000],tot[110000],son[110000],dep[110000];
     64 void pre_tree_node(int x)
     65 {
     66     son[x]=0;tot[x]=1;
     67     for(int k=last[x];k;k=a[k].next)
     68     {
     69         int y=a[k].y;
     70         if(y!=fa[x])
     71         {
     72             fa[y]=x;dep[y]=dep[x]+1;
     73             pre_tree_node(y);
     74             if(tot[y]>tot[son[x]])son[x]=y;
     75             tot[x]+=tot[y];
     76         }
     77     }
     78 }
     79 int tp,id,ys[110000],top[110000],L[110000],R[110000];
     80 void pre_tree_edge(int x,int tp)
     81 {
     82     ys[x]=++id;top[x]=tp;L[x]=id;
     83     if(son[x]!=0)pre_tree_edge(son[x],tp);
     84     for(int k=last[x];k;k=a[k].next)
     85     {
     86         int y=a[k].y;
     87         if(y!=son[x] && y!=fa[x])pre_tree_edge(y,y);
     88     }
     89     R[x]=id;
     90 }
     91 LL sol(int x,int y)
     92 {
     93     LL ans=0;int tx=top[x],ty=top[y];
     94     while(tx!=ty)
     95     {
     96         if(dep[tx]>dep[ty])swap(tx,ty),swap(x,y);
     97         ans+=getsum(1,ys[ty],ys[y]);
     98         y=fa[ty];ty=top[y];
     99     }
    100     if(x==y)return ans+getsum(1,ys[x],ys[x]);
    101     else
    102     {
    103         if(dep[x]>dep[y])swap(x,y);
    104         return ans+getsum(1,ys[x],ys[y]);
    105     }
    106 }
    107 LL d[100000];
    108 int main()
    109 {
    110     scanf("%d%d",&n,&m);len=0;memset(last,0,sizeof(last));
    111     for(int i=1;i<=n;i++)scanf("%lld",&d[i]);
    112     for(int i=1;i<n;i++)
    113     {
    114         int x,y;scanf("%d%d",&x,&y);
    115         ins(x,y);ins(y,x);
    116     }
    117     fa[1]=0;dep[1]=0;pre_tree_node(1);
    118     id=0;pre_tree_edge(1,1);
    119     trlen=0;bt(1,id);for(int i=1;i<=n;i++)change(1,ys[i],ys[i],d[i]);
    120     while(m--)
    121     {
    122         int opt,x;LL y;scanf("%d",&opt);
    123         if(opt==1)scanf("%d%lld",&x,&y),change(1,ys[x],ys[x],y);
    124         else if(opt==2)
    125         {
    126             scanf("%d%lld",&x,&y);
    127             change(1,L[x],R[x],y);
    128         }
    129         else {scanf("%d",&x);printf("%lld
    ",sol(1,x));}
    130     }
    131     return 0;
    132 }                       
  • 相关阅读:
    lnmp环境搭建
    Git常用命令
    博客园写随笔环境搭建
    Win常用软件
    Docker环境搭建
    ESP-8266 RTOS 环境搭建
    查看Linux信息
    博客园markdown语法
    Java后台技术(TDDL)
    Java后台技术(Dubbo入门)
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8810425.html
Copyright © 2011-2022 走看看