版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/88045944
这个树剖sb题我写什么呢?
欧拉序
欧拉序:一个点入栈的时候加入序列,成为左括号,出栈的时候再加入一次,成为右括号
修改就可以直接在欧拉序序列上修改
这里右括号保存与左括号符号相反的值,达到一个类似差分的目的
欧拉序要开两倍空间
Code:
#include<bits/stdc++.h>
#define rs tr[k].r
#define ls tr[k].l
#define mid ((ls+rs)>>1)
#define ll long long
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=2e5+5;
int n;
ll a[N];int pos[N*2];
ll work[N<<1];
namespace segtree{
struct seg{int l,r;ll add,sum;}tr[N<<2];
inline void pushup(int k){tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;}
inline void pushadd(int k,ll v){tr[k].add+=v;tr[k].sum+=((ll)pos[rs]-pos[ls-1])*v;}
inline void pushdown(int k){if(tr[k].add){pushadd(k<<1,tr[k].add);pushadd(k<<1|1,tr[k].add);tr[k].add=0;}}
void build(int k,int l,int r){
ls=l,rs=r;tr[k].add=0;
if(l==r) {tr[k].sum=(pos[ls]-pos[ls-1])*work[l];return;}
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
pushup(k);
}
void modify(int k,int ql,int qr,ll v){
if(ls>qr || rs<ql || ql>qr) return;
if(ql<=ls && rs<=qr) return pushadd(k,v);
pushdown(k);
if(qr<=mid) modify(k<<1,ql,qr,v);
else if(ql>mid) modify(k<<1|1,ql,qr,v);
else modify(k<<1,ql,mid,v),modify(k<<1|1,mid+1,qr,v);
pushup(k);
}
ll ask(int k,int ql,int qr){
if(ls>qr || rs<ql) return 0;
if(ql<=ls && rs<=qr) return tr[k].sum;
pushdown(k);
if(qr<=mid) return ask(k<<1,ql,qr);
else if(ql>mid) return ask(k<<1|1,ql,qr);
else return ask(k<<1,ql,mid)+ask(k<<1|1,mid+1,qr);
}
}
int m;
using namespace segtree;
int vis[N<<1],nxt[N<<1],head[N<<1],tot=0;
int l[N<<1],r[N<<1],cnt=0,pt[N];
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
void dfs(int v){
pt[v]=1;l[v]=++cnt;work[cnt]=a[v];pos[cnt]=1;
for(int i=head[v];i;i=nxt[i]){
if(pt[vis[i]]) continue;
dfs(vis[i]);
}
r[v]=++cnt;work[cnt]=a[v];pos[cnt]=-1;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int x,y,i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x);
dfs(1);n*=2;
for(int i=1;i<=n;i++) pos[i]+=pos[i-1];
build(1,1,n);
while(m--){
int op=read();
if(op==3) cout<<ask(1,1,l[read()])<<"\n";
else{
int x=read();ll v=(ll)read();
if(op==1) modify(1,l[x],l[x],v),modify(1,r[x],r[x],v);
else modify(1,l[x],r[x],v);
}
}
return 0;
}