0
点赞
收藏
分享

微信扫一扫

Change FZU - 2277

​​点击打开链接​​

线段树区间更新单点查询 

对于每一个更新 都看作是一次对等差数列的首项以及公差的改变 为了用实现线段树 要把首项转到根结点 又因为是单点查询 所以也不用考虑区间和的问题

G++WA VC++AC 真的有毒

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1000000007
#define ll long long

struct node1
{
int v;
int next;
};

struct node2
{
int l;
int r;
ll a;
ll d;
};

node1 edge[600010];
node2 tree[1200010];
int first[300010],mp1[300010],mp2[300010],deep[300010],sum[300010];
int n,num;

void addedge(int u,int v)
{
edge[num].v=v;
edge[num].next=first[u];
first[u]=num++;
return;
}

void dfs(int cur,int pre,int dp)
{
int i,v;
num++;
mp1[cur]=num;
mp2[num]=cur;
deep[cur]=dp;
sum[cur]=1;
for(i=first[cur];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(v!=pre)
{
dfs(v,cur,dp+1);
sum[cur]+=sum[v];
}
}
return;
}

void pushdown(int cur)
{
if(tree[cur].a!=0)
{
tree[2*cur].a=(tree[2*cur].a+tree[cur].a)%M;
tree[2*cur+1].a=(tree[2*cur+1].a+tree[cur].a)%M;
tree[cur].a=0;
}
if(tree[cur].d!=0)
{
tree[2*cur].d=(tree[2*cur].d+tree[cur].d)%M;
tree[2*cur+1].d=(tree[2*cur+1].d+tree[cur].d)%M;
tree[cur].d=0;
}
return;
}

void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].a=0;
tree[cur].d=0;
if(l==r) return;
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
return;
}

void update(ll a,ll d,int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].a=((tree[cur].a+a)%M+M)%M;
tree[cur].d=((tree[cur].d+d)%M+M)%M;
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) update(a,d,pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) update(a,d,pl,pr,2*cur+1);
return;
}

ll query(int tar,int cur)
{
ll res;
int v;
if(tree[cur].l==tree[cur].r)
{
v=mp2[tree[cur].l];
res=(tree[cur].a+((deep[v]-1)*tree[cur].d)%M+M)%M;
return res;
}
pushdown(cur);
if(tar<=tree[2*cur].r) return query(tar,2*cur);
else return query(tar,2*cur+1);
}

int main()
{
ll x,k,a,d;
int t,q,op,u,v;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
build(1,n,1);
memset(first,-1,sizeof(first));
num=0;
for(u=2;u<=n;u++)
{
scanf("%d",&v);
addedge(u,v);
addedge(v,u);
}
num=0;
dfs(1,-1,1);
scanf("%d",&q);
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%lld%lld",&v,&x,&k);
a=x+k*(deep[v]-1),d=-k;
update(a,d,mp1[v],mp1[v]+sum[v]-1,1);
}
else
{
scanf("%d",&v);
printf("%lld\n",query(mp1[v],1));
}
}
}
return 0;
}

 


举报

相关推荐

0 条评论