純靜態登入頁面
阿新 • • 發佈:2021-02-15
題意:
題解:
這已經是很裸的樹鏈剖分了。。。
直接套模板
程式碼:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int maxn=2e5+10;
inline int read()
{
int s=0,w=1;
char c=getchar();
while( c<'0'||c>'9')
{
if(c=='-')
w=-w;
c=getchar();
}
while(c>='0'&&c<='9')
{
s=s*10+c-'0';
c=getchar();
}
return s*w;
}
int n,m;
int e,beg[maxn],nex[maxn],to[maxn],w[maxn],wt[maxn];
int a[maxn<<2],laz[maxn<<2];
int son[maxn],id[maxn],fa[maxn],cnt,dep[maxn],siz[ maxn],top[maxn];
int res=0;
//id[]表示時間戳(即在鏈當中的編號)
//dep[]表示該節點的深度
//siz[]表示該節點子樹的大小【方便修改子樹數值時呼叫線段樹】
//top[]表示重量開端
#define mid ((l+r)>>1)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define len (r-l+1)
inline void add(int x,int y)//鏈式前向星
{
to[++e]=y;
nex[e]=beg[x];
beg[ x]=e;
}
//-----------------------以下為線段樹-----------------------------------
inline void build(int rt,int l,int r)
{
if(l==r)
{
a[rt]=wt[l];
return;
}
build(lson);
build(rson);
a[rt]=(a[rt<<1]+a[rt<<1|1]);
}
inline void pushdown(int rt,int lenn)
{
laz[rt<<1]+=laz[rt];
laz[rt<<1|1]+=laz[rt];
a[rt<<1]+=laz[rt]*(lenn-(lenn>>1));
a[rt<<1|1]+=laz[rt]*(lenn>>1);
laz[rt]=0;
}
inline void query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
res+=a[rt];
return;
}
else
{
if(laz[rt])
pushdown(rt,len);
if(L<=mid)
query(lson,L,R);
if(R>mid)
query(rson,L,R);
}
}
void update(int node,int left,int right,int pos,int v)
{
if(left==right)
{
a[node]+=v;
return ;
}
int midn=(left+right)/2;
if(laz[node])//注意:單點修改可能會影響lazy標記,需要處理一下
pushdown(node,right-left+1);
if(pos<=midn)
{
update(2*node,left,midn,pos,v);
}
else
{
update(2*node+1,midn+1,right,pos,v);
}
a[node]=a[2*node]+a[2*node+1];
}
inline void updata(int rt,int l,int r,int L,int R,int k)
{
if(L<=l&&r<=R)
{
laz[rt]+=k;
a[rt]+=k*len;
}
else
{
if(laz[rt])
pushdown(rt,len);
if(L<=mid)
updata(lson,L,R,k);
if(R>mid)
updata(rson,L,R,k);
a[rt]=(a[rt<<1]+a[rt<<1|1]);
}
}
//-----------------------以上為線段樹-----------------------------------
inline void dfs1(int x,int f,int deep)
{
dep[x]=deep;
fa[x]=f;
siz[x]=1;
int maxson=-1;
for(register int i=beg[x];i;i=nex[i])
{
int y=to[i];
if(y==f)
continue;
dfs1(y,x,deep+1);
siz[x]+=siz[y];
if(siz[y]>maxson)
son[x]=y,maxson=siz[y];
}
}
inline void dfs2(int x,int topf)
{
id[x]=++cnt;
wt[cnt]=w[x];
top[x]=topf;
if(!son[x])
return;
dfs2(son[x],topf);
for(register int i=beg[x];i;i=nex[i])
{
int y=to[i];
if(y==fa[x]||y==son[x])
continue;
dfs2(y,y);
}
}
inline int qRange(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y);
res=0;
query(1,1,n,id[top[x]],id[x]);
ans+=res;
x=fa[top[x]];
}
if(dep[x]>dep[y])
swap(x,y);
res=0;
query(1,1,n,id[x],id[y]);
ans+=res;
return ans;
}
signed main()
{
n=read();
m=read();
for(int i=1;i<=n;i++)
w[i]=read();
for(int i=1;i<n;i++)
{
int a,b;
a=read();
b=read();
add(a,b);
add(b,a);
}
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
while(m--)
{
int k,x,y;
k=read();
if(k==1)
{
x=read();
y=read();
update(1,1,n,id[x],y);
}
if(k==2)
{
x=read();
y=read();
updata(1,1,n,id[x],id[x]+siz[x]-1,y);
}
if(k==3)
{
x=read();
printf("%lld\n",qRange(1,x));
}
}
return 0;
}