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\n",sol(1,x));}
130     }
131     return 0;
132 }                       

原文地址:https://www.cnblogs.com/CHerish_OI/p/8810425.html

时间: 2024-10-30 08:14:01

bzoj4034: [HAOI2015]树上操作(树剖)的相关文章

【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树

[BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. Input 第一行包含两个整数 N, M .表示点数和操作数. 接下来一行 N 个整数,表示树中节点的初始权值. 接下来 N-1 行每行三个正整数 fr, to

[HAOI2015]树上操作 -树链剖分

1963. [HAOI2015]树上操作 [题目描述] 有一棵点数为N的树,以点1为根,且树点有权值.然后有M个操作,分为三种: 操作1:把某个节点x的点权增加a. 操作2:把某个节点x为根的子树中所有点的点权都增加a. 操作3:询问某个节点x到根的路径中所有点的点权和. [输入格式] 第一行两个整数N,M,表示点数和操作数. 接下来一行N个整数,表示树中节点的初始权值. 接下来N-1行每行两个正整数fr,to,表示该树中存在一条边(fr,to). 再接下来M行,每行分别表示一次操作.其中第一个

bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树

4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4352  Solved: 1387[Submit][Status][Discuss] Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有

bzoj千题计划242:bzoj4034: [HAOI2015]树上操作

http://www.lydsy.com/JudgeOnline/problem.php?id=4034 dfs序,树链剖分 #include<cstdio> #include<iostream> using namespace std; #define N 100001 typedef long long LL; int n,a[N]; int front[N],nxt[N<<1],to[N<<1],tot; int fa[N],siz[N],dep[N]

BZOJ 4034[HAOI2015]树上操作(树链剖分)

Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a .操作 3 :询问某个节点 x 到根的路径中所有点的点权和.Input 第一行包含两个整数 N, M .表示点数和操作数.接下来一行 N 个整数,表示树中节点的初始权值.接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) .再接下来 M 行,

[BZOJ4034][HAOI2015]树上操作

题目描述 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 输入描述 Input Description 第一行包含两个整数 N, M .表示点数和操作数.接下来一行 N 个整数,表示树中节点的初始权值.接下来 N-1 行每行三个正整数 fr, to , 表示该

[HAOI2015]树上操作(树链剖分)

[HAOI2015]树上操作(luogu) Description 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 输入格式 第一行包含两个整数 N, M .表示点数和操作数.接下来一行 N 个整数,表示树中节点的初始权值.接下来 N-1 行每行两个正整数 from, to

BZOJ 4034 HAOI2015 树上操作

4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 6033  Solved: 1959[Submit][Status][Discuss] Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有

P3178 [HAOI2015]树上操作

P3178 [HAOI2015]树上操作 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a .操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 输入输出格式 输入格式: 第一行包含两个整数 N, M .表示点数和操作数.接下来一行 N 个整数,表示树中节点的初始权值.接下来 N-1 行每行两个正整数 from, to , 表示该树中存