【NOIP2016提高A组集训第16场11.15】三部曲
来源:互联网 发布:手机翻墙用什么软件 编辑:程序博客网 时间:2024/05/17 03:16
题目大意
因为外来的入侵,国王决定在某些城市加派士兵。所有城市初始士兵数量为0。当城市i被加派了k名士兵时。城市i的所有子城市需要被加派k+1名士兵。这些子城市的所有子城市需要被加派k+2名士兵。以此类推。
q个操作:1. 给城市i增派k名士兵 2. 询问以i为根的子树的士兵总数。
n≤50000 q≤100000
分析
在子树上维护信息的题,一般可以考虑求出dfs序,然后用数据结构维护。
考虑一个增派操作的某一个节点x,如果它要增加k个人,它的儿子就都要增加k+1个人,然而儿子的深度都比x的深度大1。所以可以考虑把k和后面加的东西分开。
一个比较简单的思路:把增派k人拆成增派k’+dep(x)人。那么对于整个子树,前面的k’部分,全部节点加的是一样的。后面的无论操作有几次,加的都是dep(x),只要记录节点x被多少个插入操作覆盖即可。
用线段树维护即可。时间复杂度
#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int N=50005,M=131077;typedef long long LLSS;int n,h[N],nxt[N],m,Q[M],QM[M],Dfn[N],Size[N],tot,KM[M],Dep[N],Fa[N],L[M],R[M],D[M],P[N];LLSS ans,T[M];char c;int read(){ int x=0,sig=1; for (c=getchar();c<'0' || c>'9';c=getchar()) if (c=='-') sig=-1; for (;c>='0' && c<='9';c=getchar()) x=x*10+c-48; return x*sig;}void Dfs(int x){ Dfn[x]=++tot; Dep[x]=Dep[Fa[x]]+1; P[tot]=x; for (int i=h[x];i;i=nxt[i]) { Dfs(i); Size[x]+=Size[i]+1; }}void Init(int l,int r,int x){ L[x]=l; R[x]=r; if (l==r) { D[x]=Dep[P[l]]; return; } int Mid=l+r>>1; Init(l,Mid,x<<1); Init(Mid+1,r,x<<1|1); D[x]=D[x<<1]+D[x<<1|1];}void Push_down(int x){ int lt=x<<1,rt=lt|1; if (KM[x]!=0) { KM[lt]+=KM[x]; T[lt]+=(LLSS)KM[x]*(R[lt]-L[lt]+1); KM[rt]+=KM[x]; T[rt]+=(LLSS)KM[x]*(R[rt]-L[rt]+1); KM[x]=0; } if (QM[x]!=0) { QM[lt]+=QM[x]; T[lt]+=(LLSS)QM[x]*D[lt]; QM[rt]+=QM[x]; T[rt]+=(LLSS)QM[x]*D[rt]; QM[x]=0; }}void Ins(int a,int b,int v,int x){ if (L[x]==a && R[x]==b) { QM[x]++; KM[x]+=v; T[x]+=D[x]+(LLSS)v*(R[x]-L[x]+1); return; } Push_down(x); int lt=x<<1,rt=lt|1; if (b<=R[lt]) Ins(a,b,v,lt); else if (a>=L[rt]) Ins(a,b,v,rt); else { Ins(a,R[lt],v,lt); Ins(L[rt],b,v,rt); } T[x]=T[lt]+T[rt];}void Query(int a,int b,int x){ if (L[x]==a && R[x]==b) { ans+=T[x]; return; } Push_down(x); int lt=x<<1,rt=lt|1; if (b<=R[lt]) Query(a,b,lt); else if (a>=L[rt]) Query(a,b,rt); else { Query(a,R[lt],lt); Query(L[rt],b,rt); }}int main(){ freopen("truetears.in","r",stdin); freopen("truetears.out","w",stdout); n=read(); m=read(); for (int i=2;i<=n;i++) { Fa[i]=read(); nxt[i]=h[Fa[i]]; h[Fa[i]]=i; } Dfs(1); Init(1,n,1); while (m--) { for (c=getchar();c!='A' && c!='Q';c=getchar()); if (c=='A') { int x=read(),k=read(); Ins(Dfn[x],Dfn[x]+Size[x],k-Dep[x],1); }else { int x=read(); ans=0; Query(Dfn[x],Dfn[x]+Size[x],1); printf("%lld\n",ans); } } fclose(stdin); fclose(stdout); return 0;}
0 0
- 【NOIP2016提高A组集训第16场11.15】三部曲
- 三部曲 【NOIP2016提高A组集训第16场11.15】
- 【JZOJ4895】【NOIP2016提高A组集训第16场11.15】三部曲
- 【NOIP2016提高A组集训第16场11.15】兔子
- NOIP2016提高A组集训第16场11.15 总结
- 【JZOJ4896】【NOIP2016提高A组集训第16场11.15】兔子
- 【JZOJ4894】【NOIP2016提高A组集训第16场11.15】SJR的直线
- 【NOIP2016提高A组集训第3场10.31】方程式
- 【NOIP2016提高A组集训第5场11.2】夕阳
- 方程式 【NOIP2016提高A组集训第3场10.31】
- 【NOIP2016提高A组集训第7场11.4】连锁店
- NOIP2016提高A组集训第8场11.5 总结
- 【NOIP2016提高A组集训第9场11.7】Simple
- NOIP2016提高A组集训第8场11.5总结
- 【NOIP2016提高A组集训第9场11.7】平均数
- 【NOIP2016提高A组集训第5场11.2】寻找
- 【NOIP2016提高A组集训第5场11.2】行走
- NOIP2016提高A组集训第11场11.9 总结
- 自相关函数,互相关函数
- shell命令
- 机器学习算法 -- 集成学习
- MongoDB学习笔记:(1)、MongoDB在Win10下的安装
- iOS分类 UIView
- 【NOIP2016提高A组集训第16场11.15】三部曲
- JavaScript 页面自动执行(加载)js的几种方法
- JavaScriot prototype 和 __proto__ 详解
- ReactNative Could not install the app on the device
- CCF 201604-3 路径解析 java实现w
- 蓝桥杯_C语言_本科B——啤酒和饮料
- Gson 解析遇到的奇怪问题
- CentOS 7 安装Docker服务
- Android手机窃听器的实现