【51nod1462】树据结构
来源:互联网 发布:3d打鱼源码 编辑:程序博客网 时间:2024/06/06 04:26
Description
给一颗以1为根的树。
每个点有两个权值:vi, ti,一开始全部是零。
Q次操作:
读入o, u, d
o = 1 对u到根上所有点的vi += d
o = 2 对u到根上所有点的ti += vi * d
最后,输出每个点的ti值(n, Q <= 100000)
有50%的数据N,Q <= 10000
注:所有数64位整数不会爆。
Solution
我们考虑用树剖来做这道题。
对于一个操作x,我们用树链剖分,但现在问题来了,怎样维护v和t呢?
我们对于线段树的每一位存下一个v,v1,t分别表示仅在该子树拥有的操作1,该子树及其父亲传下的操作1以及该子树同时拥有t。每一次操作有一个lzv,lzt表示懒标记下传。下传时v1 son+=lzv,lzv son+=lzv,t son+=t+lzt*v,lzt son+=t+lzt*v,最后把lzt,lzv,t清零。
Code
#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#define ll long longusing namespace std;const int maxn=6e5+5;struct code{ ll t,v,v1,lv,lt; }f[maxn];int first[maxn],last[maxn],next[maxn],b[maxn],dfn[maxn],size[maxn],son[maxn],fa[maxn],top[maxn];ll n,i,t,j,k,l,x,y,z,p,num,m,ans[maxn];void lian(int x,int y){ last[++num]=y;next[num]=first[x];first[x]=num;}void dg(int x){ int t;size[x]++; for (t=first[x];t;t=next[t]){ fa[last[t]]=x;dg(last[t]),size[x]+=size[last[t]]; if (size[last[t]]>size[son[x]]) son[x]=last[t]; }}void dg1(int x){ int t;b[++num]=x;dfn[x]=num; if (son[x]) top[son[x]]=top[x],dg1(son[x]); for (t=first[x];t;t=next[t]) if (last[t]!=son[x]) top[last[t]]=last[t],dg1(last[t]);}void make(int v){ int x=v*2,y=v*2+1; f[x].v1+=f[v].lv;f[x].lv+=f[v].lv,f[x].t+=f[v].t+f[x].v*f[v].lt;f[x].lt+=f[v].lt; f[y].v1+=f[v].lv;f[y].lv+=f[v].lv,f[y].t+=f[v].t+f[y].v*f[v].lt;f[y].lt+=f[v].lt; f[v].lv=f[v].lt=f[v].t=0;}void change(int l,int r,int v,int x,int y){ int mid=(l+r)/2; if ((f[v].lv||f[v].lt)&&l<r) make(v); if (l>=x && r<=y){ if (z==1)f[v].v+=p,f[v].v1+=p,f[v].lv+=p; else f[v].t+=f[v].v1*p,f[v].lt+=p; return; } if (l<=y && mid>=x) change(l,mid,v*2,x,y); if (mid<y && r>=x) change(mid+1,r,v*2+1,x,y);}void find(int l,int r,int v){ int mid=(l+r)/2; if ((f[v].lv||f[v].lt)&&l<r) make(v); if (l==r){ ans[b[l]]=f[v].t; return; } find(l,mid,v*2);find(mid+1,r,v*2+1);}int main(){// freopen("data.in","r",stdin);freopen("data.out","w",stdout); scanf("%lld",&n); for (i=2;i<=n;i++) scanf("%lld",&x),lian(x,i); dg(1);top[1]=1;num=0; dg1(1);scanf("%lld",&m); for (i=1;i<=m;i++){ scanf("%lld%lld%lld",&z,&x,&p); while (x) change(1,n,1,dfn[top[x]],dfn[x]),x=fa[top[x]]; } find(1,n,1); for (i=1;i<=n;i++) printf("%lld\n",ans[i]);}
1 0
- 【51Nod1462】树据结构
- 【51nod1462】树据结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 树结构
- 模仿TreeView结构的树结构类
- 树结构做情节结构的问题
- 三种数据结构
- redis5种数据结构
- 下面的程序执行输出几个hello
- Android-从数据库到Content Provider
- 绝对能用-动态设置textview的drawableleft、drawableright、drawabletop、drawablebottom
- 关于字符编码 GB2312,UTF-8,GBK,BIG5
- sprintf用法详解
- 【51nod1462】树据结构
- Python数据结构与算法分析学习记录(1)——基于Problem Solving with Algorithms and Data Structures using Python的学习
- 在Keil C51函数中加入ASM代码
- MySQL 中间件汇总比较 .
- 备忘录模式(状态变化)
- HDU1072-Nightmare
- MarkDown笔记(一)
- Python数据挖掘相关机器学习库
- ajax(三)之省市二级菜单联动(从sql获取数据),无刷新翻页