(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
Catalog
Problem:Portal传送门
原题目描述在最下面。
区间更新,单点求和。数据范围1e5。
Solution:
听说要用读入挂,然后我不用读入挂也过了!不加读入挂
1390ms
1390
m
s
,加读入挂
828ms
828
m
s
,你们可以去
vj
v
j
上看我的代码哟。
节点
u
u
加,节点
u
u
的儿子加
x−y
x
−
y
,节点
u
u
的孙子加
x−2×y
x
−
2
×
y
,依次类推。
其实我们可以在给
u
u
的子树区间更新的时候,可以更新数值,这样就是普通的区间更新,对于查询我们再特殊处理一下查询就是
∑(x+dep[]×y)−dep[i]×∑y
∑
(
x
+
d
e
p
[
]
×
y
)
−
d
e
p
[
i
]
×
∑
y
。
这样的话我们线段树每个节点保存两个值
sum1
s
u
m
1
和
sum2
s
u
m
2
.
sum1
s
u
m
1
就是所有
(x+dep[u]×y)
(
x
+
d
e
p
[
u
]
×
y
)
的和,而
sum2
s
u
m
2
就是所有
y
y
的和。普通区间更新,查询答案时输出即可。
AC_Code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lson rt<<1
#define rson rt<<1|1
#define read(x) scanf("%d", &x)
using namespace std;
typedef long long LL;
const int N = 600000+7;
const int MXM = 3e5+7;
const LL MOD = 1000000007;
int n, q;
struct lp{
int l,r;
LL sum1,sum2;
}cw[N<<2];
int tid[N],rtid[N],dep[N];
struct lh{
int v, nex;
}edge[N];
int head[N], tot, top;
inline void insert(int a,int b){
edge[++tot].v=b;edge[tot].nex=head[a];
head[a]=tot;
}
void dfs(int u,int dd){
tid[u] = ++top;
dep[u]=dd;
for(int i=head[u];~i;i=edge[i].nex){
int v = edge[i].v;
dfs(v,dd+1);
}
rtid[u]=top;
}
void build(int l,int r,int rt){
cw[rt].l=l;cw[rt].r=r;
cw[rt].sum1=cw[rt].sum2=0;
if(l==r)return;
int mid = (l+r)>>1;
build(l,mid,lson);build(mid+1,r,rson);
}
inline void Add(LL &a, LL b){
a += b;
while(a>=MOD)a-=MOD;
}
void push_down(int rt){
LL a = cw[rt].sum1, b = cw[rt].sum2;
if(a)Add(cw[lson].sum1, a);
if(a)Add(cw[rson].sum1, a);
if(b)Add(cw[lson].sum2, b);
if(b)Add(cw[rson].sum2, b);
cw[rt].sum1 = cw[rt].sum2 = 0;
}
void update(int L,int R,LL y,LL z,int rt){
int l = cw[rt].l,r=cw[rt].r,mid=(l+r)>>1;
if(L<=l&&r<=R){
Add(cw[rt].sum1, y);
Add(cw[rt].sum2, z);
return;
}
push_down(rt);
if(L>mid)update(L,R,y,z,rson);
else if(R<=mid)update(L,R,y,z,lson);
else{
update(L,mid,y,z,lson),update(mid+1,R,y,z,rson);
}
}
LL query(int p,int k,int rt){
if(cw[rt].l==cw[rt].r){
return ((cw[rt].sum1-cw[rt].sum2*k%MOD)+MOD)%MOD;
}
push_down(rt);
int mid = (cw[rt].l+cw[rt].r)>>1;
if(p<=mid)return query(p,k,lson);
return query(p,k,rson);
}
int main(){
int tim;read(tim);
while(tim--){
read(n);
for(int i=0;i<=n;++i)head[i]=-1;
tot = -1;top = 0;
for(int i = 2, u; i <= n; ++i){
read(u);
insert(u,i);
}
dfs(1,1);
read(q);
build(1,n,1);
while(q--){
int op,x;
int y,z;
read(op);
if(op == 1){
read(x);read(y);read(z);
update(tid[x],rtid[x],(y*1LL+dep[x]*1LL*z%MOD)%MOD,z,1);
}else{
read(x);
printf("%lld\n", query(tid[x],dep[x],1));
}
}
}
return 0;
}