题目描述

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a 。操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

输入输出格式

输入格式:

第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, 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 。

思路:

  裸树剖;

来,上代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> #define LL long long
#define maxn 100005 using namespace std; struct TreeNodeType {
LL l,r,dis,mid,flag;
};
struct TreeNodeType tree[maxn<<]; struct EdgeType {
LL to,next;
};
struct EdgeType edge[maxn<<]; LL if_z,n,m,deep[maxn],top[maxn],end[maxn];
LL flag[maxn],size[maxn],head[maxn],cnt;
LL dis[maxn],dis_[maxn],f[maxn]; char Cget; inline void in(LL &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(LL u,LL v)
{
cnt++;
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
} void search_1(LL now,LL fa)
{
LL pos=cnt++;
f[now]=fa,deep[now]=deep[fa]+;
for(LL i=head[now];i;i=edge[i].next)
{
if(edge[i].to==fa) continue;
search_1(edge[i].to,now);
}
size[now]=cnt-pos;
} void search_2(LL now,LL chain)
{
flag[now]=++cnt,top[now]=chain;
LL pos=;dis_[cnt]=dis[now];
for(LL i=head[now];i;i=edge[i].next)
{
if(edge[i].to==f[now]) continue;
if(size[edge[i].to]>size[pos]) pos=edge[i].to;
}
if(pos) search_2(pos,chain);
for(LL i=head[now];i;i=edge[i].next)
{
if(edge[i].to==f[now]||edge[i].to==pos) continue;
search_2(edge[i].to,edge[i].to);
}
end[now]=cnt;
} void tree_build(LL now,LL l,LL r)
{
tree[now].l=l,tree[now].r=r;
if(l==r)
{
tree[now].dis=dis_[l];
return ;
}
tree[now].mid=(l+r)>>;
tree_build(now<<,l,tree[now].mid);
tree_build(now<<|,tree[now].mid+,r);
tree[now].dis=tree[now<<].dis+tree[now<<|].dis;
} void tree_change(LL now,LL l,LL r,LL x)
{
if(tree[now].l==l&&tree[now].r==r)
{
tree[now].dis+=(r-l+)*x;
tree[now].flag+=x;
return ;
}
if(tree[now].flag)
{
tree[now<<].dis+=(tree[now].mid-tree[now<<].l+)*tree[now].flag;
tree[now<<|].dis+=(tree[now<<|].r-tree[now].mid)*tree[now].flag;
tree[now<<].flag+=tree[now].flag;
tree[now<<|].flag+=tree[now].flag;
tree[now].flag=;
}
if(l>tree[now].mid) tree_change(now<<|,l,r,x);
else if(r<=tree[now].mid) tree_change(now<<,l,r,x);
else
{
tree_change(now<<,l,tree[now].mid,x);
tree_change(now<<|,tree[now].mid+,r,x);
}
tree[now].dis=tree[now<<|].dis+tree[now<<].dis;
} LL tree_query(LL now,LL l,LL r)
{
if(tree[now].l==l&&tree[now].r==r) return tree[now].dis;
if(tree[now].flag)
{
tree[now<<].dis+=(tree[now].mid-tree[now<<].l+)*tree[now].flag;
tree[now<<|].dis+=(tree[now<<|].r-tree[now].mid)*tree[now].flag;
tree[now<<].flag+=tree[now].flag;
tree[now<<|].flag+=tree[now].flag;
tree[now].flag=;
}
if(l>tree[now].mid) return tree_query(now<<|,l,r);
else if(r<=tree[now].mid) return tree_query(now<<,l,r);
else return tree_query(now<<,l,tree[now].mid)+tree_query(now<<|,tree[now].mid+,r);
} LL solve_query(LL x,LL y)
{
LL pos=;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
pos+=tree_query(,flag[top[x]],flag[x]);
x=f[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
pos+=tree_query(,flag[x],flag[y]);
return pos;
} int main()
{
in(n),in(m);
for(LL i=;i<=n;i++) in(dis[i]);
LL u,v;
for(LL i=;i<n;i++)
{
in(u),in(v);
edge_add(u,v);
edge_add(v,u);
}
cnt=,search_1(,);
cnt=,search_2(,);
tree_build(,,n);
while(m--)
{
in(u);
if(u==)
{
in(u),in(v);
tree_change(,flag[u],flag[u],v);
}
else if(u==)
{
in(u),in(v);
tree_change(,flag[u],end[u],v);
}
else
{
in(v);
cout<<solve_query(,v);
putchar('\n');
}
}
return ;
}

AC日记——[HAOI2015]树上操作 洛谷 P3178的更多相关文章

  1. AC日记——I Hate It 洛谷 P1531

    题目背景 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 题目描述 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的 ...

  2. AC日记——天天爱跑步 洛谷 P1600

    天天爱跑步 思路: 树上差分+分层动态线段树: (伏地膜,跪烂xxy) 代码: #include <bits/stdc++.h> using namespace std; #define ...

  3. AC日记——[SDOI2015]星际战争 洛谷 P3324

    题目描述 3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战. 在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai.当一个巨型机器人的装甲值 ...

  4. AC日记——联合权值 洛谷 P1351

    题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离. ...

  5. AC日记——软件包管理器 洛谷 P2416

    题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...

  6. AC日记——神奇的幻方 洛谷 P2615(大模拟)

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  7. AC日记——[CQOI2009]DANCE跳舞 洛谷 P3153

    [CQOI2009]DANCE跳舞 思路: 二分+最大流: 代码: #include <cstdio> #include <cstring> #include <iost ...

  8. AC日记——松江1843路 洛谷七月月赛

    松江1843路 思路: 三分: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define ...

  9. AC日记——严酷的训练 洛谷 P2430

    严酷的训练 思路: 背包: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 5005 int n,m,bi[m ...

随机推荐

  1. 百度地图和高德地图的API视频教程

    学习地址: http://www.houdunren.com/houdunren18_lesson_152?vid=10228 素材地址: https://gitee.com/houdunwang/v ...

  2. js---post与get请求的区别

    request获取请求参数 最为常见的客户端传递参数方式有两种: 浏览器地址栏直接输入:一定是GET请求: 超链接:一定是GET请求: 表单:可以是GET,也可以是POST,这取决与<form& ...

  3. php-数据库连接类

    <?php class DB{ var $host; var $user; var $pwd; var $dbname; var $conn; function DB($host,$user,$ ...

  4. Objective-C中的一些特殊的数据类型

    nil nil和C语言的NULL相同,在objc/objc.h中定义.nil表示一个Objctive-C对象,这个对象的指针指向空(没有东西就是空). Nil  首字母大写的Nil和nil有一点不一样 ...

  5. Selenium WebDriver- 指定页面加载时间

    #encoding=utf-8 import unittest import time from selenium import webdriver from selenium.webdriver i ...

  6. x86 保护模式 十 分页管理机制

    x86   保护模式  十  分页管理机制 8.386开始支持分页管理机制 段机制实现虚拟地址到线性地址的转换,分页机制实现线性地址到物理地址的转换.如果不启用分页,那么线性就是物理地址 一  分页管 ...

  7. A Few Laughing Men

    A Few Laughing Men CodeChef - LAUGHMEN Balaji is a great person to hang out with. He tells really am ...

  8. Chromo开发常用插件和***工具

    地址:https://www.google.com/chrome/webstore/ ***工具:链接:http://pan.baidu.com/s/1pLakW7T 密码:2gpw Axure RP ...

  9. ACM程序设计选修课——1058: Lucky Sequence(思考)

    1058: Lucky Sequence Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 52  Solved: 6 [Submit][Status][ ...

  10. 北京集训TEST12——PA( Mortal Kombat)

    题目: Description 有一天,有N个外星人企图入侵地球.地球派出全球战斗力最强的M个人代表人类对抗外星人.根据外星的战斗规则,每个外星人应该分别与一名地球人对战(不同的外星人要与不同的地球人 ...