标签:else top vector style data- 在线 参数 模板 lib
Description
题目描述
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:
输入格式
第一行包含两个整数 N, M 。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行两个正整数 from, to , 表示该树中存在一条边 (from, to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
输出格式
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Solution
操作 1:线段树中点dfn[x]加a;
操作 2:由树链剖分遍历的顺序可知任何一棵子树中节点的dfs序<=子树的根的dfs序,
且最大的dfs序=子树的根的dfs序+子树的大小-1,于是可以直接在线段树上操作;
操作 3:简化版树剖求和模板
Code
#include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> using namespace std; const int N=1e5+10; struct node { int l,r,lc,rc; long long sum,delay; }f[N*2]; int n,u,v,m,deep[N],tot,si[N],top[N],d[N],t, fa[N],dfn[N],cnt,rt,son[N],re[N],opt,x; long long a; char s[100]; vector <int> link[N]; void dfs1(int u,int f) { si[u]=1,fa[u]=f,deep[u]=deep[f]+1; int size=link[u].size(); for(int i=0;i<size;i++) { int v=link[u][i]; if(v!=f) { dfs1(v,u); si[u]+=si[v]; if(son[u]==0 || si[son[u]]<si[v]) son[u]=v; } } } void dfs2(int u,int f) { dfn[u]=++tot,re[tot]=u; if(son[u]!=0) { top[son[u]]=top[u],dfs2(son[u],u); int size=link[u].size(); for(int i=0;i<size;i++) { int v=link[u][i]; if(v!=f && v!=son[u]) top[v]=v,dfs2(v,u); } } } long long gel(int g) { return f[g].r-f[g].l+1; } void push_up(int g) { int lc=f[g].lc,rc=f[g].rc; if(lc==0) return ; f[g].sum=f[lc].sum+f[rc].sum+gel(g)*f[g].delay; } void push_down(int g) { int lc=f[g].lc,rc=f[g].rc; if(lc==0 || f[g].delay==0) return ; f[lc].delay+=f[g].delay,f[rc].delay+=f[g].delay; f[lc].sum+=gel(lc)*f[g].delay,f[rc].sum+=gel(rc)*f[g].delay; f[g].delay=0; } void build(int &g,int l,int r) { g=++cnt; f[g].l=l,f[g].r=r; if(l==r) { f[g].sum=d[re[l]]; return ; } int mid=(l+r)>>1; build(f[g].lc,l,mid); build(f[g].rc,mid+1,r); push_up(g); } void add(int g,int l,int r,int k) { if(f[g].l>=l && f[g].r<=r) f[g].sum+=gel(g)*k,f[g].delay+=k; else { int mid=(f[g].l+f[g].r)/2; if(r<=mid) add(f[g].lc,l,r,k); else if(l>mid) add(f[g].rc,l,r,k); else add(f[g].lc,l,mid,k),add(f[g].rc,mid+1,r,k); push_up(g); } } long long get(int g,int l,int r) { if(f[g].l>=l && f[g].r<=r) return f[g].sum; else { push_down(g); int mid=(f[g].l+f[g].r)/2; if(r<=mid) return get(f[g].lc,l,r); else if(l>mid) return get(f[g].rc,l,r); else return get(f[g].lc,l,mid)+get(f[g].rc,mid+1,r); } } long long Get(int x) { long long sum=0; while(x!=0) { sum+=get(rt,dfn[top[x]],dfn[x]); x=fa[top[x]]; } return sum; } //操作 1 :把某个节点 x 的点权增加 a 。 //操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。 //操作 3 :询问某个节点 x 到根的路径中所有点的点权和。 int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&d[i]); for(int i=1;i<n;i++) { scanf("%d%d",&u,&v); link[u].push_back(v); link[v].push_back(u); } dfs1(1,0); top[1]=1,dfs2(1,0); build(rt,1,tot); while(m--) { scanf("%d%d",&opt,&x); if(opt==3) printf("%lld\n",Get(x)); else { scanf("%lld",&a); if(a!=0) { if(opt==1) add(rt,dfn[x],dfn[x],a); else if(opt==2) add(rt,dfn[x],dfn[x]+si[x]-1,a); } } } return 0; }
标签:else top vector style data- 在线 参数 模板 lib
原文地址:https://www.cnblogs.com/hsez-cyx/p/12251267.html