前置知识倍增https://oi-wiki.org/basic/binary-lifting/ 题目给出的是一个类似于内向基环树的图,根据对于每个i,a[Next[i]]跟a[i]关系可以建立一个边权图假设x,y都是正数,那么对于每次询问的最大前缀和都是走完即可,接下来就是处理负数对结局的影响.类似的我们可以利用倍增的思想额外去维护这个最大前缀和pre,前缀和就是sum,f(i,j)代表第i给点恰好走2j步,发现对于任意的区间l,r,f(l+r).sum=fl.sum+fr.sum 而最大前缀和有两种情况取max,从左边的序列 l 贡献 f(l+r).pre=max(f(l+r).pre,fl.pre)和从右边的序列r 贡献,因为必须是前缀需要加上左边序列的元素和 f(l+r).pre=max(fl.sum+fr.pre,f(l+r).pre) 接下来就可以在倍增数组上维护f(i,j)了
f(i+j).sum=f(i,j−1).sum+f(f(i,j−1),j−1).sum f(i+j).pre=max(f(i+j).pre,f(i,j−1).pre)
小美正在一张有向但定连通的图上玩游戏。这张图包含n个点,第i个点的权值为a,当小美从i移动到 Nexti时,游戏规则如下:
如果aNeati>ai,小美的金币将增加x;
如果aNexti≤ai,小美的金币将增加y。
小美会提出q次询问,每个询问从某个点u出发,移动不超过k步,最多能获得多少金币。
第一行输入四个整数n,q,x,y(1≤n,q≤2×105,−106≤x,y≤106)代表图上点的数量、询问的次数、规则中金币的增加量。 第二行输入n个整数Next1,Nextz,...,Nextn(1≤Nexti≤n)表示第i个节点下一步的位置。 第三行输入n个整数a1,a2,...,an(1≤ai≤106),表示第i个节点的权值。 此后q行,每行输入两个整数u,k(1≤u≤n,1≤k≤109) 代表一次询问的起始点和步数限制。
对于每一次询问,在一行上输出一个整数,代表最多能获得的金币数量。
输入
4 5 -2 3
2 3 4 1
5 10 3 2
1 1
1 2
1 4
2 4
2 7
输出
0
1
4
6
8
说明
该样例如下图所示:
●对于第一次询问,走一步会扣除2金币,但是可以选择站在原地不走; ●对于第二次询问,走一步时金币数量减至−2,走两步金币数量变更为−2+3=1。
输入
4 4 2 -1
2 3 1 4
1 2 3 1000000
1 3
3 3
2 2
4 1000000
输出
4
3