P3178 [HAOI2015]树上操作

Posted kafuuchino

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3178 [HAOI2015]树上操作相关的知识,希望对你有一定的参考价值。

P3178 [HAOI2015]树上操作

树链剖分模板简化(右转模板区)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;}
template <typename T> inline T max(T &a,T &b) {return a>b ?a:b;}
template <typename T> inline void read(T &x){
    char c=getchar(); x=0; bool f=1;
    while(!isdigit(c)) f= !f||c==- ? 0:1,c=getchar();
    while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
    x= f ? x:-x;
}
template <typename T> inline void output(T x){
    if(!x) {putchar(48); return ;}
    if(x<0) putchar(-),x=-x;
    int wt[50],l=0;
    while(x) wt[++l]=x%10,x/=10;
    while(l) putchar(wt[l--]+48);
}
typedef long long ll;
typedef int arr[100002];
int n,m,cnt,tot,nxt[200002],poi[200002];
arr d,fa,siz,bgs,tp,id,tmp,val,hd,ed;
ll add[400008],sum[400008];
inline void add_(int x,int y){
    nxt[ed[x]]=++cnt; hd[x]= hd[x] ? hd[x]:cnt;
    ed[x]=cnt; poi[cnt]=y;
}
inline void pushdown(int o,int l,int r){
    int lc=o<<1,rc=o<<1|1,mid=l+((r-l)>>1);
    sum[lc]+=add[o]*(mid-l+1);
    sum[rc]+=add[o]*(r-mid);
    add[lc]+=add[o]; add[rc]+=add[o];
    add[o]=0;
}
inline void build(int o,int l,int r){
    if(l==r) {sum[o]=tmp[l]; return;}
    int lc=o<<1,rc=o<<1|1,mid=l+((r-l)>>1);
    build(lc,l,mid); build(rc,mid+1,r);
    sum[o]=sum[lc]+sum[rc];
}
inline void update(int o,int l,int r,int x1,int x2,int v){
    if(x1<=l&&r<=x2){
        add[o]+=v;
        sum[o]+=1LL*v*(r-l+1);
        return ;
    }pushdown(o,l,r);
    int lc=o<<1,rc=o<<1|1,mid=l+((r-l)>>1);
    if(x1<=mid) update(lc,l,mid,x1,x2,v);
    if(x2>mid) update(rc,mid+1,r,x1,x2,v);
    sum[o]=sum[lc]+sum[rc];
}
inline ll query(int o,int l,int r,int x1,int x2){
    if(x1<=l&&r<=x2) return sum[o];
    pushdown(o,l,r); ll res=0;
    int lc=o<<1,rc=o<<1|1,mid=l+((r-l)>>1);
    if(x1<=mid) res+=query(lc,l,mid,x1,x2);
    if(x2>mid) res+=query(rc,mid+1,r,x1,x2);
    return res;
}
//------线段树------ inline
void dfs1(int x,int _fa){ d[x]=d[_fa]+1,fa[x]=_fa,siz[x]=1; for(int i=hd[x];i;i=nxt[i]) if(poi[i]!=_fa){ dfs1(poi[i],x); siz[x]+=siz[poi[i]]; if(siz[bgs[x]]<siz[poi[i]]) bgs[x]=poi[i]; } } inline void dfs2(int x,int _top){ id[x]=++tot,tmp[tot]=val[x],tp[x]=_top; if(siz[x]==1) return; dfs2(bgs[x],_top); for(int i=hd[x];i;i=nxt[i]) if(poi[i]!=fa[x]&&poi[i]!=bgs[x]) dfs2(poi[i],poi[i]); } inline ll ask(int x,int y){ ll res=0; while(d[tp[x]]!=d[tp[y]]){ if(d[tp[x]]<d[tp[y]]) swap(x,y); res+=query(1,1,n,id[tp[x]],id[x]); x=fa[tp[x]]; }if(d[x]>d[y]) swap(x,y); return res+query(1,1,n,id[x],id[y]); } int main(){ read(n),read(m); int q1,q2,q3; for(int i=1;i<=n;++i) read(val[i]); for(int i=1;i<n;++i) read(q1),read(q2),add_(q1,q2),add_(q2,q1); dfs1(1,0); dfs2(1,1); build(1,1,n); for(int i=1;i<=m;++i){ read(q1),read(q2); if(q1==1) read(q3),update(1,1,n,id[q2],id[q2],q3); else if(q1==2) read(q3),update(1,1,n,id[q2],id[q2]+siz[q2]-1,q3); else output(ask(1,q2)),putchar( ); }return 0; }

 

以上是关于P3178 [HAOI2015]树上操作的主要内容,如果未能解决你的问题,请参考以下文章

「Luogu P3178」[HAOI2015]树上操作

luogu P3178 [HAOI2015]树上操作 题解

P3178 [HAOI2015]树上操作

洛谷——P3178 [HAOI2015]树上操作

洛谷P3178 [HAOI2015]树上操作

P3178 [HAOI2015]树上操作 (树链剖分模版题)