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序+线段树 每个点所加权值不同的更多相关文章

  1. cdoj 574 High-level ancients dfs序+线段树

    High-level ancients Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/s ...

  2. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  3. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  4. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  5. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  6. POJ 3321 DFS序+线段树

    单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include < ...

  7. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  8. F - Change FZU - 2277 (DFS序+线段树)

    题目链接: F - Change FZU - 2277 题目大意: 题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作 (1) 1 v k x : a[v] += x, a[v ' ...

  9. BZOJ4551[Tjoi2016&Heoi2016]树——dfs序+线段树/树链剖分+线段树

    题目描述 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均 ...

随机推荐

  1. sequence_loss的解释

    在做seq2seq的时候,经常需要使用sequence_loss这是损失函数. 现在分析一下sequence_loss这个函数到底在做什么 # coding: utf-8 import numpy a ...

  2. 测试的Python、 Java语言之争

    现在测试行业如果不会开发语言的话是很难找到工作的,即使是一些功能测试的岗位也会要求代码语言作为技术储备,因为如果做自动化测试或者测试工具脚本开发或者接口测试等都离不开开发语言,那作为测试如果没有代码经 ...

  3. idea导入项目之后包位置报错

    解决办法:

  4. 学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat

    学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat 2019-05-09   19:28:42 注:项目(MyEclipse)创建的时候选择:Web Service Pr ...

  5. vue-导入element-ui

    安装 npm install element-ui -S 项目中导入 修改main.js import ElementUI from 'element-ui'; import 'element-ui/ ...

  6. csp-s模拟95

    近两场开始文件评测,感觉和平时真不太一样. 考试时间是多了$10min$,但处理文件.输入输出什么的杂事也是忙来忙去.这可能也最像真实的$csps$了,稍有疏忽可能都是致命伤. T1.T2挂的对拍全打 ...

  7. MySQL个人用户的安装配置详解

    1. 我的版本是 MySQL 5.7.26.0 ,因为据说 MySQL 8 的性能虽然强悍,但是兼容性还是有问题,而且发布时间不够长,没有普及,就暂时用着5.7版本. (1) 下载地址,选择使用msi ...

  8. linux下什么工具可以用来纠正文件中的拼写和排版错误?

    答: ispell,官网在此

  9. SQL-W3School-高级:SQL LEFT JOIN 关键字

    ylbtech-SQL-W3School-高级:SQL LEFT JOIN 关键字 1.返回顶部 1. SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1 ...

  10. Build Telemetry for Distributed Services之Elastic APM

    官网地址:https://www.elastic.co/guide/en/apm/get-started/current/index.html Overview Elastic APM is an a ...