zoukankan      html  css  js  c++  java
  • [HAOI2015] 树上操作

    bzoj 4034 传送门

    洛谷P3178 传送门

    线段树+树链剖分裸题。

    再次犯了把"=="打成了"="的智障错误。

    还有忘记维护节点深度......

    pengzhou:啊,这是15年省选题,水吧?

    我:嗯......

    上代码吧。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define ll long long
      5 using namespace std;
      6 
      7 int n,m;
      8 int hd[100005],to[200005],nx[200005],ec;
      9 int in[100005],out[100005],pos[100005],cc;
     10 int bv[100005];
     11 int sz[100005],d[100005],f[100005],son[100005],tp[100005];
     12 ll v[400005],lz[400005];
     13 int lb[400005],rb[400005];
     14 
     15 void edge(int af,int at)
     16 {
     17     to[++ec]=at;
     18     nx[ec]=hd[af];
     19     hd[af]=ec;
     20 }
     21 
     22 void pre(int p,int fa)
     23 {
     24     f[p]=fa;
     25     sz[p]=1;
     26     d[p]=d[fa]+1;
     27     for(int i=hd[p];i;i=nx[i])
     28     {
     29         if(to[i]==fa)continue;
     30         pre(to[i],p);
     31         sz[p]+=sz[to[i]];
     32         if(sz[to[i]]>sz[son[p]])son[p]=to[i];
     33     }
     34 }
     35 
     36 void findtp(int p)
     37 {
     38     in[p]=++cc;
     39     pos[cc]=p;
     40     if(p==son[f[p]])tp[p]=tp[f[p]];
     41     else tp[p]=p;
     42     if(son[p])findtp(son[p]);
     43     for(int i=hd[p];i;i=nx[i])
     44     {
     45         if(to[i]!=f[p]&&to[i]!=son[p])findtp(to[i]);
     46     }
     47     out[p]=cc;
     48 }
     49 
     50 void pushup(int p)
     51 {
     52     v[p]=v[p<<1]+v[p<<1|1];
     53 }
     54 
     55 void pushdown(int p)
     56 {
     57     if(!lz[p])return;
     58     v[p<<1]+=lz[p]*(ll)(rb[p<<1]-lb[p<<1]+1);
     59     v[p<<1|1]+=lz[p]*(ll)(rb[p<<1|1]-lb[p<<1|1]+1);
     60     lz[p<<1]+=lz[p];
     61     lz[p<<1|1]+=lz[p];
     62     lz[p]=0;
     63 }
     64 
     65 void build(int num,int l,int r)
     66 {
     67     lb[num]=l,rb[num]=r;
     68     if(l==r)
     69     {
     70         v[num]=(ll)bv[pos[l]];
     71         return;
     72     }
     73     int mid=(l+r)>>1;
     74     build(num<<1,l,mid);
     75     build(num<<1|1,mid+1,r);
     76     pushup(num);
     77 }
     78 
     79 void add(int num,int l,int r,ll val)
     80 {
     81     if(l<=lb[num]&&r>=rb[num])
     82     {
     83         lz[num]+=val;
     84         v[num]+=val*(ll)(rb[num]-lb[num]+1);
     85         return;
     86     }
     87     pushdown(num);
     88     int mid=(lb[num]+rb[num])>>1;
     89     if(l<=mid)add(num<<1,l,r,val);
     90     if(r>mid)add(num<<1|1,l,r,val);
     91     pushup(num);
     92 }
     93 
     94 ll sum(int num,int l,int r)
     95 {
     96     if(l<=lb[num]&&r>=rb[num])return v[num];
     97     ll ret=0;
     98     pushdown(num);
     99     int mid=(lb[num]+rb[num])>>1;
    100     if(l<=mid)ret+=sum(num<<1,l,r);
    101     if(r>mid)ret+=sum(num<<1|1,l,r);
    102     return ret;
    103 }
    104 
    105 void ask(int x)
    106 {
    107     int y=1;
    108     ll ret=0;
    109     while(tp[x]!=tp[y])
    110     {
    111         if(d[tp[x]]<d[tp[y]])swap(x,y);
    112         ret+=sum(1,in[tp[x]],in[x]);
    113         x=f[tp[x]];
    114     }
    115     if(d[x]>d[y])swap(x,y);
    116     ret+=sum(1,in[x],in[y]);
    117     printf("%lld
    ",ret);
    118 }
    119 
    120 int main()
    121 {
    122     scanf("%d%d",&n,&m);
    123     for(int i=1;i<=n;i++)scanf("%d",&bv[i]);
    124     for(int i=1;i<n;i++)
    125     {
    126         int ff,tt;
    127         scanf("%d%d",&ff,&tt);
    128         edge(ff,tt);
    129         edge(tt,ff);
    130     }
    131     pre(1,1);
    132     findtp(1);
    133     build(1,1,n);
    134     for(int i=1;i<=m;i++)
    135     {
    136         int op,p;
    137         scanf("%d%d",&op,&p);
    138         if(op==1)
    139         {
    140             int a;
    141             scanf("%d",&a);
    142             add(1,in[p],in[p],(ll)a);
    143         }
    144         if(op==2)
    145         {
    146             int a;
    147             scanf("%d",&a);
    148             add(1,in[p],out[p],(ll)a);
    149         }
    150         if(op==3)ask(p);
    151     }
    152 }
    树上操作
  • 相关阅读:
    Linux C++ 网络编程学习系列(2)——多路IO之select实现
    Linux C++ 网络编程学习系列(1)——端口复用实现
    Linux c++ vim环境搭建系列(5)——vim使用
    Linux c++ vim环境搭建系列(4)——vim插件安装配置使用
    Linux c++ vim环境搭建系列(3)——Ubuntu18.04.4编译安装youcompleteme
    0512String类
    0511Object类和异常
    Leetcode--53. 最大子序和
    哥德巴赫猜想 Java实现
    面向对象案例-学生信息管理系统V1.1
  • 原文地址:https://www.cnblogs.com/cervusy/p/9643156.html
Copyright © 2011-2022 走看看