题意:

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
 
思路:
处理出这棵树的欧拉序,入栈时为这个点的正权,出栈时为这个点的负权
对于操作1,对x入栈点加a,出栈点减a
对于操作2,对x入栈点到x出栈点所有的点执行操作1
对于操作3,即查询点1的入栈点到x入栈点的点权和
 
在正常的区间加线段树中,有一个add,add对区间和sum[root]的贡献为(r-l+1)*add
对这一题,我们记入栈点的flg为1,出栈点的为-1,那么在flg求和的情况下,add对区间和的贡献为flg[root]*add
正常搞线段树即可
 
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional> #define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) using namespace std; typedef double db;
typedef long double ldb;
typedef long long ll;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL; const db eps = 1e-;
const int mod = ;
const int maxn = 2e6+;
const int maxm = 2e6+;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0); int n, m;
ll a[maxn];
vector<int>v[maxn];
int tot;
int in[maxn],out[maxn];//树上i的出、入在rk位置
ll rk[maxn];
int vis[maxn];//in 1 , out 0
void dfs(int x, int fa){
++tot;in[x]=tot;rk[tot]=a[x];vis[tot]=;
for(int i = ; i < (int)v[x].size(); i++){
int y = v[x][i];
if(y!=fa)dfs(y,x);
}
++tot;out[x]=tot;rk[tot]=-a[x];vis[tot]=;
}
ll flg[maxn],lazy[maxn];
ll sum[maxn];
void build(int l, int r, int root){
if(l==r){
if(vis[l])flg[root]=;
else flg[root]=-;
sum[root]=rk[l];
return;
}
int mid = (l+r)>>;
build(lson);
build(rson);
sum[root]=sum[lc]+sum[rc];
flg[root]=flg[lc]+flg[rc];
}
void pushdown(int l, int r, int root){
if(!lazy[root])return;
lazy[lc]+=lazy[root];
lazy[rc]+=lazy[root];
sum[lc]+=lazy[root]*flg[lc];
sum[rc]+=lazy[root]*flg[rc];
lazy[root]=;
return;
}
void update(int x, int y, int val, int l, int r, int root){
int mid = (l+r)>>;
if(x<=l&&r<=y){
lazy[root]+=val;
sum[root]+=val*flg[root];
return;
}
pushdown(l, r, root);
if(x<=mid)update(x,y,val,lson);
if(y>mid)update(x,y,val,rson);
sum[root]=sum[lc]+sum[rc];
return;
}
ll query(int x, int y, int l, int r, int root){
int mid = (l+r)>>;
if(x<=l&&r<=y)return sum[root];
pushdown(l, r, root);
ll ans = ;
if(x<=mid)ans+=query(x,y,lson);
if(y>mid)ans+=query(x,y,rson);
return ans;
} int main() {
scanf("%d %d", &n, &m);
for(int i = ; i <= n; i++){
scanf("%lld", &a[i]);
}
for(int i = ; i <= n-; i++){
int x, y;
scanf("%d %d" ,&x, &y);
v[x].pb(y);
v[y].pb(x);
}
dfs(,-);
build(,tot,);
while(m--){
int op, x, y;
scanf("%d", &op);
if(op==){
scanf("%d %d" ,&x ,&y);
update(in[x],in[x],y,,tot,);
update(out[x],out[x],y,,tot,);
}
else if(op==){
scanf("%d %d", &x ,&y);
update(in[x],out[x],y,,tot,);
}
else{
scanf("%d", &x);
printf("%lld\n",query(,in[x],,tot,));
}
}
return ;
}
/*
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. C#中DataTable中的Compute方法使用收集
  2. bzoj 2739 最远点
  3. 论Segmentation fault
  4. jquery练习(一次性赋予多个属性值)
  5. Blackfin DSP(四):BF533 EBIU之SDRAM
  6. iOS学习之UINavigationController
  7. Javascript 偏移量总结
  8. 捕获ClientDataSet.ApplyUpdates和SocketConnection异常
  9. 【STM32】STM32 GPIO模式理解
  10. Python爬虫学习之爬美女图片
  11. cocos2d-x 3.0 播放MP4视频
  12. 跟我学ASP.NET MVC之七:SportsStrore一个完整的购物车
  13. java第八章JDBC
  14. 笔记javascript
  15. linux安装jdk和tomcat命令
  16. xmanagr 注册机执行ubuntu 桌面程序,ubuntu无需安装 桌面环境
  17. Sphinx(coreseek)一些记录
  18. Import Projects from git
  19. spring mvc 默认页面
  20. Python中操作HTTP请求的urllib模块详解

热门文章

  1. Spring MVC系列之模型绑定(SpringBoot)(七)
  2. 变量的取用与设定:echo,变量设定规则,unset
  3. DevExpress 控件用法笔记(VB)
  4. 清晰架构(Clean Architecture)的Go微服务: 依赖注入(Dependency Injection)
  5. 深入理解协程(四):async/await异步爬虫实战
  6. css 脱离文档流
  7. [bzoj2152] [洛谷P2634] 聪聪可可
  8. pandas时间序列常用操作
  9. Qt常用UI控件读取、写入方法
  10. HDU-6185-Covering(推递推式+矩阵快速幂)