按dfs序一个一个加入线段树,可以让任何一颗子树的节点在线段树中连续,于是就可以用线段树维护整棵树了

  和树剖的思想是一样的,大概一眼就看出来了,但是写了两个半天(躺

  总结:记住以后写完数据结构或者数字比较大的题用搜索搜一下乘号想想会不会爆long long TAT

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=,mod=1e9+;
struct poi{int too,pre;}e[maxn];
struct zs{ll sum,delta;}tree[maxn];
int n,m,x,y,z,tot,cnt;
int last[maxn],a[maxn],l[maxn],r[maxn],w[maxn];
char s[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
inline void dfs(int x,int fa)
{
a[++cnt]=w[x];l[x]=cnt;
for(int i=last[x];i;i=e[i].pre)
if(e[i].too!=fa)dfs(e[i].too,x);
r[x]=cnt;
}
inline void pushup(int x){tree[x].sum=tree[x<<].sum+tree[x<<|].sum;}
inline void pushdown(int x,int l,int r)
{
if(!tree[x].delta)return;
tree[x<<].delta+=tree[x].delta;
tree[x<<|].delta+=tree[x].delta;
int mid=(l+r)>>;
tree[x<<].sum+=tree[x].delta*(mid-l+);
tree[x<<|].sum+=tree[x].delta*(r-mid);
tree[x].delta=;
}
inline void build(int x,int l,int r)
{
if(l==r){tree[x].sum=a[l];return;}
int mid=(l+r)>>;
build(x<<,l,mid);build(x<<|,mid+,r);
pushup(x);
}
inline void insert(int x,int l,int r,int cx,int sd,int delta)
{
if(l==r){if(tree[x].sum<sd)tree[x].sum+=delta;return;}
pushdown(x,l,r);
int mid=(l+r)>>;
if(cx<=mid)insert(x<<,l,mid,cx,sd,delta);
else insert(x<<|,mid+,r,cx,sd,delta);
pushup(x);
}
inline void add(int x,int l,int r,int cl,int cr,int delta)
{
if(cl<=l&&r<=cr){tree[x].delta+=delta,tree[x].sum+=1ll*delta*(r-l+);return;}
pushdown(x,l,r);
int mid=(l+r)>>;
if(cl<=mid)add(x<<,l,mid,cl,cr,delta);
if(cr>mid)add(x<<|,mid+,r,cl,cr,delta);
pushup(x);
}
inline ll query(int x,int l,int r,int cl,int cr)
{
if(cl<=l&&r<=cr)return tree[x].sum;
pushdown(x,l,r);
int mid=(l+r)>>;ll res=;
if(cl<=mid)res+=query(x<<,l,mid,cl,cr);
if(cr>mid)res+=query(x<<|,mid+,r,cl,cr);
return res;
}
int main()
{
read(n);read(m);
for(int i=;i<=n;i++)
{
read(x);read(w[i]);
x++;add(x,i);
}
dfs(,);build(,,cnt);
for(int i=;i<=m;i++)
{
scanf("%s",s+);read(x);read(y);read(z);x++;
if(s[]=='S')insert(,,cnt,l[x],y,z);
else if(query(,,cnt,l[x],r[x])<1ll*y*(r[x]-l[x]+))add(,,cnt,l[x],r[x],z);
}
for(int i=;i<=n;i++)printf("%lld\n",query(,,cnt,l[i],l[i]));
}

最新文章

  1. 关于a和b不用第三变量交换值的问题
  2. Android 7.0 UICC 分析(一)
  3. vim用法小节
  4. 王垠:完全用Linux工作
  5. BitmapData类介绍
  6. POJ 1088 滑雪 (记忆化搜索)
  7. XML工具类 - XmlUtils.java
  8. FileTable初体验
  9. Redis相关命令
  10. (NO.00003)iOS游戏简单的机器人投射游戏成形记(十一)
  11. 【App】Android Studio 海马玩
  12. 机器学习: 共轭梯度算法(PCG)
  13. Python中的类(上)
  14. 进程间通信--POSIX共享内存
  15. C语言初学
  16. [学习笔记]编译sensetime发表的Single View Stereo Matching(SVS)遇到的问题
  17. java 面试 -- 4
  18. APM飞控系统详细介绍
  19. 【转载】rabbitmq的发布确认和事务
  20. mysql之数据类型以及操作数据表

热门文章

  1. 安装SQLSEVER与MySQL
  2. servlet和Jsp的复习整理
  3. win32绘制自定义类窗口导致绘制11个窗口的解决办法
  4. php redis和java混用问题
  5. 火狐metamask账号
  6. jquery datatable 常用例子
  7. js如何处理字符串中带有↵字符
  8. Python中的eval
  9. PHPCMS v9表单向导中怎么加入验证码
  10. UVALive - 6856 Circle of digits 后缀数组+二分