cdoj 574 High-level ancients dfs序+线段树 每个点所加权值不同
High-level ancients
Time Limit: 20 Sec
Memory Limit: 256 MB
题目连接
http://acm.uestc.edu.cn/#/problem/show/574
Description
Love8909 is keen on the history of Kingdom ACM. He admires the heroic undertakings of Lxhgww and Haibo. Inspired by those sagas, Love8909 picked up his courage and tried to build up his own kingdom. He named it as A230.
After hard working for several years, Love8909 is about to fulfill his dream. However, there is still one thing to do: setting up the defense network. As Kingdom EDC looks at territory and people of A230 fiercely as a tiger does, Love8909 has to make it as soon as possible.
The defense network Love8909 wants to use is the same as the one used by Lxhgww and Haibo. He also connects all cities with roads which form a tree structure, and the capital city is City 1, which is the root of this tree. Love8909 sends commands to inform cities to add soldiers. The command, being same to those of the ancients, with two values, X and K, means sending K soldiers to City X, sending K+1 soldiers to sons of City X, sending K+2 soldiers to sons of sons of City X and so on. Initially there are no soldiers in any city.
Love8909 may adjust the arrangement of soldiers ever and again. He asks questions about how many soldiers in the subtree rooted at City X. A subtree rooted at City X includes City X itself and all of its descendants. As Love8909's military counselor, you are responsible to complete all his commands and answer his questions.
Input
The first line of the input will be an integer T (T≤20) indicating the number of cases.
For each case, the first line contains two integers: N P, representing the number of cities in A230 and number of operations given by love8909.
The next line lists N−1 integers, in which the ith number, denoted as Xi+1, represents there is a road from City Xi+1 to City i+1. Note that the City 1has been omitted. 1≤Xi+1≤N for 2≤i≤N.
Then P lines follow, each gives an operation. Each operation belongs to either kind:
A X K
. An adding-soldier command.Q X
. A question about how many soldiers in the subtree rooted at City X.
We guarantee that the cities form a rooted tree and the root is at City 1, which is the capital.
1≤N≤50000, 1≤P≤100000, 1≤X≤N, 0≤K≤1000.
Output
For each case, print Case #k:
first in a single line, in which k represents the case number which starts from 1. Then for each Query X
operation, print the answer in a single line.
Sample Input
1
7 10
1 1 2 2 5 5
Q 1
A 2 1
Q 1
Q 2
Q 5
A 5 0
Q 5
A 3 1
Q 1
Q 2
Sample Output
Case #1:
0
11
11
8
10
14
13
HINT
题意
给你一棵以1为根的树,有两个操作
1.A x k,让x增加k,x的儿子增加k+1,x的孙子增加k+2....x的t代儿子增加k+t
2.Q x , 查询x的子树的权值和是多少
题解:
处理子树的问题,我们一般会想到用dfs序将其转换成一段连续的区间。
子树中每个点所加的值和深度有关。我们用dp[x]表示x的深度,那么x的子树+val,对于x子树某节点i权值+d[i]-dp[x]+val。
这样可以把更新操作改成两部分
1.这个区间+val-dp[x]
2.每个点+dp[i]
关键在于如何处理第二个问题。其实不难,我们可以建一颗线段树,线段树每个节点加一个dpsum[x]记录这个区间的深度和,再加一个c[x]记录这个区间被更新过多少次。其余的和普通线段树没什么区别了。
那么权值和=\(sum[ls]+sum[rs]+dpsum[x]*c[x]+lazy[x]*len\)。
sum[ls]表示左半区间的和,sum[rs]表示右半区间的和,lazy[x]表示对于整个区间所加值,len表示区间长度。
更深层次地剖析:
我把这类问题抽象一下,就是给一个区间[l,r],再给一个数k,每个点的权值+a[i]*k(l<=i<=r),然后支持区间求和,想想是不是。
这个方法非常有用,对于区间加上等差数列也很适用。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100050
ll n,m,cas=0;
ll tot,last[N];
ll cnt,Size[N],dp[N],rk[N],kth[N];
struct Tree{ll l,r,j,c,sum,dpsum;}tr[N<<2];
struct Edge{ll from,to,s;}edges[N<<1];
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
void AddEdge(ll x,ll y)
{
edges[++tot]=Edge{x,y,last[x]};
last[x]=tot;
}
void dfs(ll x,ll pre)
{
rk[x]=++cnt;
kth[cnt]=x;
Size[x]=1;
dp[x]=dp[pre]+1;
for(ll i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==pre)continue;
dfs(e.to,x);
Size[x]+=Size[e.to];
}
}
void push_up(ll x)
{
ll len=tr[x].r-tr[x].l+1;
tr[x].sum=tr[x].j*len;
tr[x].sum+=tr[x].c*tr[x].dpsum;
if (len==1)return ;
tr[x].sum+=tr[x<<1].sum+tr[x<<1|1].sum;
}
void push_down(ll x)
{
Tree &a=tr[x<<1],&b=tr[x<<1|1];
a.j+=tr[x].j;
b.j+=tr[x].j;
a.c+=tr[x].c;
b.c+=tr[x].c;
push_up(x<<1);
push_up(x<<1|1);
tr[x].j=0;
tr[x].c=0;
}
void bt(ll x,ll l,ll r)
{
tr[x].l=l; tr[x].r=r; tr[x].j=0; tr[x].c=0; tr[x].sum=0;
if (l==r)
{
tr[x].dpsum=dp[kth[l]];
return;
}
ll mid=(l+r)>>1;
bt(x<<1,l,mid);
bt(x<<1|1,mid+1,r);
tr[x].dpsum=tr[x<<1].dpsum+tr[x<<1|1].dpsum;
}
void update(ll x,ll l,ll r,ll tt)
{
if (l<=tr[x].l&&tr[x].r<=r)
{
tr[x].j+=tt;
tr[x].c++;
push_up(x);
return ;
}
ll mid=(tr[x].l+tr[x].r)>>1;
push_down(x);
if (l<=mid)update(x<<1,l,r,tt);
if (mid<r)update(x<<1|1,l,r,tt);
push_up(x);
}
ll query(ll x,ll l,ll r)
{
if(l<=tr[x].l&&tr[x].r<=r)
return tr[x].sum;
ll mid=(tr[x].l+tr[x].r)>>1,ans=0;
push_down(x);
if (l<=mid)ans=query(x<<1,l,r);
if (mid<r)ans+=query(x<<1|1,l,r);
push_up(x);
return ans;
}
void work()
{
printf("Case #%lld:\n",++cas);
read(n); read(m);
for(ll i=2;i<=n;i++)
{
ll x;
read(x);
AddEdge(i,x);
AddEdge(x,i);
}
dfs(1,0);
bt(1,1,n);
for(ll i=1;i<=m;i++)
{
char id; ll x,tt;
read_char(id); read(x);
if (id=='Q')
{
printf("%lld\n",query(1,rk[x],rk[x]+Size[x]-1));
}
if (id=='A')
{
read(tt);
update(1,rk[x],rk[x]+Size[x]-1,tt-dp[x]);
}
}
}
void clear()
{
cnt=0; tot=0;
memset(last,0,sizeof(last));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
ll q;
read(q);
while(q--)
{
clear();
work();
}
}
cdoj 574 High-level ancients dfs序+线段树 每个点所加权值不同的更多相关文章
- cdoj 574 High-level ancients dfs序+线段树
High-level ancients Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/s ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
- POJ 3321 DFS序+线段树
单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4: 5: #include < ...
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
- F - Change FZU - 2277 (DFS序+线段树)
题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...
- BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树
题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...
随机推荐
- 如何通过Thread查看一个方法被调用的顺序
Test1 package com.dwz.concurrency.chapter11; public class Test1 { private Test2 test2 = new Test2(); ...
- cesium billboard跨域问题2
这篇主要是对上一篇博客cesium billboard出现跨域的原理分析 https://www.cnblogs.com/SmilingEye/p/11363837.html 1.源码位置 从Bill ...
- Spring框架AOP
aop技术是面向切面编程思想,作为OOP的延续思想添加到企业开发中,用于弥补OOP开发过程中的缺陷而提出的编程思想.AOP底层也是面向对象:只不过面向的不是普通的Object对象,而是特殊的AOP对象 ...
- 走进JavaWeb技术世界1:Web后端与J2EE的由来
转自:微信公众号 码农翻身 这个问题来自于QQ网友,一句两句说不清楚,索性写个文章. 我刚开始做Web开发的时候,根本没有前端,后端之说. 原因很简单,那个时候服务器端的代码就是一切:接受浏览器的请求 ...
- arcgis python xlstoshp
import xlrd # must init xlrd import arcpy # param arcpy.env.workspace = r"F:\note\python\ArcPy& ...
- 使用Eclipse对SpringBoot项目如何进行打包部署
1,打包概要介绍: 自己做了个小demo,突然想练一下如何打包发布,期间出现了两个错误,第一个是加载不到主类,第二个是加载不到jsp文件,一会会把这两个问题一一陈述,以及解决方法. 1.1,先检查po ...
- 阶段5 3.微服务项目【学成在线】_day03 CMS页面管理开发_04-新增页面-服务端-接口开发
api接口定义方法 api的微服务里面.CmsPageControllerApi内定义add方法,返回类型是CmsPageResult CmsPageResult继承了ResponseResult R ...
- Ubuntu 18.04设置1920*1080
Ubuntu升级后,发现分辨率没有1920*1080,在网上寻找了一个文章解决办法如下. 方案一(临时性,重启会失效): 1.打开终端.输入:cvt 1920 1080 出现有modeline 的提示 ...
- 查看进程的命令ps
查看进程的命令:ps aux strace -p pid(进程id) 杀死进程:kill pid(进程id)强制杀死进程:kill -9 pid(进程id) linux ps 命令查看进程状态linu ...
- VMware虚拟机下CentOS 6.5配置网络
使用NAT模式 虚拟机网络连接使用NAT模式,物理机网络连接使用Vmnet8. 虚拟机设置里面——网络适配器,网络连接选择自定义:Vmnet8 (NAT模式) 虚拟机菜单栏—编辑—虚拟网络编辑器,选择 ...