Description
Solution
离线以后点分
对于每个点,都用这个点的祖先把这个点的子树更新一遍,
考虑到操作时间早的才能更新晚的和题目中说的“路径上边权都大于等于 val”,
那就用树状数组做一下二维偏序就行了
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define dep(i,a,b) for(register int i=(b);i>=(a);--i)
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
int x=0,fl=1;char ch=gc();
for(;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for(;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
char pbuf[100000],*pp=pbuf;
inline void pc(char ch){if(pp==pbuf+100000)fwrite(pbuf,1,100000,stdout),pp=pbuf;*pp++=ch;}
inline void wri(ll x){
static char st[19];
int tp=0;
if(x<0)pc(45),x=-x;
if(!x)pc(48);
while(x)st[tp++]=x%10|48,x/=10;
while(tp)pc(st[--tp]);
}
inline void wln(ll x){wri(x),pc(10);}
inline void flush(){fwrite(pbuf,1,pp-pbuf,stdout);}
const int N=100002;
struct node{
int x,y,v;
node(){}
node(int x_,int y_,int v_){x=x_,y=y_,v=v_;}
bool operator <(node a)const{return x<a.x;}
}A[N],B[N];
struct kk{
int to,ne,w;
}e[N<<1];
int dep[N],h[N],tot,tot1,tot2,op[N],x,y,z,u,sz[N],n,m,mx[N],rt,st[N];
ll t[N],ans[N];
bool vis[N];
vector<node>md[N];
vector<int>q[N],V;
void add(int x,int y,int z){e[++tot]=(kk){y,h[x],z},h[x]=tot;}
void clear(int x){
for (;x<=m;x+=x&-x) t[x]=0;
}
void add(int x,int y){
for (;x<=m;x+=x&-x) t[x]+=y;
}
ll query(int x){
ll s=0;
for (;x;x^=x&-x) s+=t[x];
return s;
}
void getrt(int u,int fa){
V.push_back(u);
sz[u]=1,mx[u]=0;
for (int i=h[u],v;i;i=e[i].ne)
if (!vis[v=e[i].to] && v!=fa) getrt(v,u),sz[u]+=sz[v],mx[u]=max(mx[u],sz[v]);
}
void init(int u,int fa){
for (int i=h[u],v;i;i=e[i].ne)
if ((v=e[i].to)!=fa) dep[v]=dep[u]+1,init(v,u);
}
void dfs1(int u,int w){
for (int i=0;i<md[u].size();i++)
if (md[u][i].x<=w) A[++tot1]=md[u][i];
for (int i=h[u],v;i;i=e[i].ne)
if (!vis[v=e[i].to] && dep[v]<dep[u]) dfs1(v,min(w,e[i].w));
}
void dfs2(int u,int fa,int w){
for (int i=0;i<q[u].size();i++) B[++tot2]=node(w,q[u][i],0);
for (int i=h[u],v;i;i=e[i].ne)
if (!vis[v=e[i].to] && v!=fa && dep[v]>dep[u]) dfs2(v,u,min(w,e[i].w));
}
void solve(int u){
tot1=tot2=0;
dfs1(u,1e9);
dfs2(u,0,1e9);
sort(A+1,A+tot1+1);
sort(B+1,B+tot2+1);
int j=1;
rep(i,1,tot2){
for (;j<=tot1 && A[j].x<=B[i].x;j++) add(A[j].y,A[j].v);
ans[B[i].y]+=query(B[i].y);
}
rep(j,1,tot1) clear(A[j].y);
}
void work(int u){
V.clear();
getrt(u,0);
rt=0;
if (!V.size()) return;
for (int i=0;i<V.size();i++){
int v=V[i];
mx[v]=max(mx[v],sz[u]-sz[v]);
if (mx[v]<mx[rt]) rt=v;
}
u=rt;
solve(u),vis[u]=1;
for (int i=h[u],v;i;i=e[i].ne)
if (!vis[v=e[i].to]) work(v);
}
int main(){
n=rd(),m=rd();
rep(i,1,n) st[i]=rd();
rep(i,1,n-1) x=rd(),y=rd(),z=rd(),add(x,y,z),add(y,x,z);
rep(i,1,m){
op[i]=rd();
if (op[i]==2){
x=rd(),y=rd(),u=rd();//x是chg,y是val
md[u].push_back(node(y,i,x));
}else{
x=rd();
ans[i]=st[x];
q[x].push_back(i);
}
}
dep[0]=-1,init(1,0);
mx[0]=1e9;
work(1);
rep(i,1,m)
if (op[i]==1) wln(ans[i]);
flush();
}