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有标记,其他结点均 ...
随机推荐
- 爬虫之操作excel
几种常用模块的使用方法 注释:Excel 2003 即XLS文件有大小限制即65536行256列,所以不支持大文件,而Excel 2007以上即XLSX文件的限制则为1048576行16384列 下面 ...
- XXE外部实体注入漏洞——PHP
前言 XXE Injection即XML External Entity Injection,也就是XML外部实体注入攻击.漏洞是在对非安全的外部实体数据进行处理时引发的安全问题. 在XML1.0标准 ...
- python中的匿名函数
python 使用 lambda 来创建匿名函数. 所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数. lambda 只是一个表达式,函数体比 def 简单很多. lambda的主体是一 ...
- oracle自定义排序和NULL值排序
1.自定义顺序 当我们希望将某个查询结果指定的显示顺序展示的时候 order by case when column1=1 then 0 case when column1=1 then 1 else ...
- linux C file format analysis
c语言文件格式 source file file.c C source, ASCII text pretreatment 预处理文件 file.i C source, ASCII text assem ...
- sed中使用变量及变量中存在特殊字符‘/’处理
sed中使用变量,普通的处理方式无法解析变量 如当前file文件中存在字符串pedis,现将其替换为redis [root@localhost work]# cat file pedis 如下两种替换 ...
- web开发的三层架构
Web层 接收客户端发送过来的数据,然后需要将数据传递给service层 Service层 业务逻辑层:业务:比如检验用户名的是否存在,如果不存在则需要把用户的数据存储在数据库中,如果存在,给web返 ...
- Python基础-day04
函数基础 目标 函数的快速体验 函数的基本使用 函数的参数 函数的返回值 函数的嵌套调用 在模块中定义函数 01. 函数的快速体验 1.1 快速体验 所谓函数,就是把 具有独立功能的代码块 组织为一个 ...
- k8s学习之资料参考网址(持续更新)
此文章持续更新关于学习k8s生态的参考网址: 二进制方式搭建 (此部署方式是一步一步的部署,过程清晰) https://github.com/opsnull/follow-me ...
- WordPress自定义菜单和修改去除多余的css
这里主要是用于模板制作的,一般前端已经写好了,我们只要将前端的内容套用WordPress后台就可以了. 所以我们在模板制作过程中,需要自定义WordPress菜单. 在functions.php文件中 ...