三部曲
来源:互联网 发布:淘宝批发在哪里进货 编辑:程序博客网 时间:2024/06/10 13:16
题目大意
对一颗n个节点的树操作。
有两种操作,第一种是对子树j,j的点权+k,j的儿子们点权+k+1,j的孙子们点权+k+2,以此类推。
第二种操作询问子树点权和。
线段树
修改操作实际上是对子树每个点i加上k-d[j]+d[i]
标记可以写成(a,b)表示一个点权为x的点i经过后变成x+a+d[i]*b
显然这个标记可合并而且容易求和。
线段树维护即可。
#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;const int maxn=50000+10;ll tree[maxn*4],sum[maxn*4],a[maxn*4],b[maxn*4];int h[maxn],go[maxn],nxt[maxn],d[maxn],dfn[maxn],nfd[maxn],size[maxn];int i,j,k,l,t,n,m,tot,top;char ch;int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f;}void add(int x,int y){ go[++tot]=y; nxt[tot]=h[x]; h[x]=tot;}void dfs(int x){ dfn[x]=++top; nfd[top]=x; int t=h[x]; size[x]=1; while (t){ d[go[t]]=d[x]+1; dfs(go[t]); size[x]+=size[go[t]]; t=nxt[t]; }}void build(int p,int l,int r){ a[p]=b[p]=0; if (l==r){ sum[p]=d[nfd[l]]; tree[p]=0; return; } int mid=(l+r)/2; build(p*2,l,mid); build(p*2+1,mid+1,r); sum[p]=sum[p*2]+sum[p*2+1];}char get(){ char ch=getchar(); while (ch!='A'&&ch!='Q') ch=getchar(); return ch;}void mark(int p,int l,int r,ll c,ll d){ tree[p]+=(ll)c*(r-l+1)+d*sum[p]; a[p]+=c; b[p]+=d;}void down(int p,int l,int r){ int mid=(l+r)/2; if (a[p]||b[p]){ mark(p*2,l,mid,a[p],b[p]); mark(p*2+1,mid+1,r,a[p],b[p]); a[p]=b[p]=0; }}void change(int p,int l,int r,int a,int b,ll c,ll d){ if (l==a&&r==b){ mark(p,l,r,c,d); return; } down(p,l,r); int mid=(l+r)/2; if (b<=mid) change(p*2,l,mid,a,b,c,d); else if (a>mid) change(p*2+1,mid+1,r,a,b,c,d); else{ change(p*2,l,mid,a,mid,c,d); change(p*2+1,mid+1,r,mid+1,b,c,d); } tree[p]=tree[p*2]+tree[p*2+1];}ll query(int p,int l,int r,int a,int b){ if (l==a&&r==b) return tree[p]; down(p,l,r); int mid=(l+r)/2; if (b<=mid) return query(p*2,l,mid,a,b); else if (a>mid) return query(p*2+1,mid+1,r,a,b); else return query(p*2,l,mid,a,mid)+query(p*2+1,mid+1,r,mid+1,b);}int main(){ freopen("truetears.in","r",stdin);freopen("truetears.out","w",stdout); n=read();m=read(); fo(i,2,n){ j=read(); add(j,i); } d[1]=1; dfs(1); build(1,1,n); while (m--){ ch=get(); if (ch=='A'){ j=read();k=read(); change(1,1,n,dfn[j],dfn[j]+size[j]-1,k-d[j],1); } else{ j=read(); printf("%lld\n",query(1,1,n,dfn[j],dfn[j]+size[j]-1)); } }}
0 0
- 三部曲
- 三部曲
- 租房三部曲
- 測試人員面試三部曲
- 电影三部曲
- 爱情三部曲
- 程序员三部曲
- 皇后三部曲
- RCU三部曲
- ROR三部曲
- 人生三部曲
- 软件工程三部曲
- 程序员三部曲
- 泡妞三部曲
- 程序三部曲
- Axure三部曲
- 实习三部曲
- 认知三部曲
- 什么是形式参数,什么是实际参数,它们的区别和各自的定义是什么
- SEO经典面试题
- Windows 使用 virtualenv
- SpannableString文本类详解
- C++中的多态
- 三部曲
- java 网络编程
- ActiveMQ 使用
- mybatis OGNL应用
- redis上线 准备(安装遇到的问题+优化)
- PL/SQL报错:无法解析指定的连接标识符
- Error:Could not find property 'assembleRelease' on project ':app'
- POJ 3694 Network
- scrollTo与scrollBy的区别