BZOJ4034 树上操作(树剖 线段树大模板)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4034 树上操作(树剖 线段树大模板)相关的知识,希望对你有一定的参考价值。
BZOJ4034
long long 是大坑点
貌似long long 跟int 乘起来会搞事情?...
A了这题线段树和树剖的基础OK
嘛 重点过掉的还是线段树区间更新的lazy tag吧
#include<cstdio> #include<cstring> #define N 100001 using namespace std; struct ed{ int nxt,to; }e[N*2]; int ne=0,head[N]; long long int w0[N]; struct t{ int l,r; long long sum,add; }tree[N*4]; int father[N],son[N],hson[N],id[N],reid[N],top[N],cnt=0; int deep[N]; int n,m; void init1(int cur,int fat,int d) { deep[cur]=d; father[cur]=fat; son[cur]=0; for(int i=head[cur];i;i=e[i].nxt) { int v=e[i].to; if(v==fat) continue; init1(v,cur,d+1); son[cur]+=1+son[v]; if(son[v]>=son[hson[cur]]) hson[cur]=v; } } void init2(int cur,int up) { id[cur]=++cnt; reid[cnt]=cur; top[cur]=up; if(hson[cur]) init2(hson[cur],up); for(int i=head[cur];i;i=e[i].nxt) { int v=e[i].to; if(v==hson[cur]||v==father[cur]) continue; init2(v,v); } } void build(int L,int R,int node) { tree[node].l=L; tree[node].r=R; if(L==R) { tree[node].sum=w0[reid[L]]; return ; } int mid=(L+R)>>1; build(L,mid,node*2); build(mid+1,R,node*2+1); tree[node].sum=tree[node*2].sum+tree[node*2+1].sum; } void pushdown(int node) { long long int k=tree[node].add; tree[node].add=0; node=node*2; tree[node].add+=k; tree[node+1].add+=k; tree[node].sum+=k*(tree[node].r-tree[node].l+1); tree[node+1].sum+=k*(tree[node+1].r-tree[node+1].l+1); } void update(int L,int R,long long int val,int node) { if(L>tree[node].r || R<tree[node].l) return; if(L<=tree[node].l && R>=tree[node].r) { tree[node].sum+=(tree[node].r-tree[node].l+1)*val; tree[node].add+=val; return; } if(tree[node].add) pushdown(node); update(L,R,val,node*2); update(L,R,val,node*2+1); tree[node].sum=tree[node*2].sum+tree[node*2+1].sum; } long long int getsum(int L,int R,int node) { if(L>tree[node].r || R<tree[node].l) return 0; if(L<=tree[node].l && R>=tree[node].r) return tree[node].sum; pushdown(node); return getsum(L,R,node*2)+getsum(L,R,node*2+1); } long long int Qsum(int v) { long long int ans=0; while(top[v]!=1) { ans+=getsum(id[top[v]],id[v],1); v=father[top[v]]; } ans+=getsum(1,id[v],1); return ans; } void ade(int from,int to) { e[++ne].nxt=head[from]; head[from]=ne; e[ne].to=to; } int main() { scanf("%d %d",&n,&m); memset(tree,0,sizeof(tree)); for(int i=1;i<=n;i++) scanf("%lld",&w0[i]); for(int i=1;i<n;i++) { int a,b; scanf("%d %d",&a,&b); ade(a,b); ade(b,a); } init1(1,0,1); init2(1,1); build(1,cnt,1); for(int i=1;i<=m;i++) { int flag; scanf("%d",&flag); if(flag==1) { int pt; long long val;//val这里是大迷点 scanf("%d %lld",&pt,&val); update(id[pt],id[pt],val,1); } else if(flag==2) { int root; long long int val; scanf("%d %lld",&root,&val); update(id[root],id[root]+son[root],val,1); } else { int v; scanf("%d",&v); printf("%lld\n",Qsum(v)); } } return 0; }
以上是关于BZOJ4034 树上操作(树剖 线段树大模板)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树
BZOJ-4034: [HAOI2015]树上操作 (线段树+DFS序)