第八届福建省大学生程序设计竞赛-重现赛(F Problem 2277 Change)DFS序+树状数组

Problem 2277 Change
Accept: 38 Submit: 241
Time Limit: 2000 mSec Memory Limit : 262144 KB

Problem Description

There is a rooted tree with n nodes, number from 1-n. Root’s number is 1.Each node has a value ai.

Initially all the node’s value is 0.

We have q operations. There are two kinds of operations.

1 v x k : a[v]+=x , a[v’]+=x-k (v’ is child of v) , a[v’’]+=x-2*k (v’’ is child of v’) and so on.

2 v : Output a[v] mod 1000000007(10^9 + 7).

Input

First line contains an integer T (1 ≤ T ≤ 3), represents there are T test cases.

In each test case:

The first line contains a number n.

The second line contains n-1 number, p2,p3,…,pn . pi is the father of i.

The third line contains a number q.

Next q lines, each line contains an operation. (“1 v x k” or “2 v”)

1 ≤ n ≤ 3*10^5

1 ≤ pi < i

1 ≤ q ≤ 3*10^5

1 ≤ v ≤ n; 0 ≤ x < 10^9 + 7; 0 ≤ k < 10^9 + 7

Output

For each operation 2, outputs the answer.

Sample Input

1
3
1 1
3
1 1 2 1
2 1
2 2
Sample Output

2
1
题意:给你一个n个节点n-1条边的树,1为树根。q次操作
1: v x k : a[v]+=x , a[v’]+=x-k (v’ is child of v) , a[v’’]+=x-2*k (v’’ is child of v’) and so on.应该能看懂吧,描述起来有点难。
2:询问v点的val。
题解:对于1操作来说,假设v是这个点,设x为v的所有子节点,则
val[x]+=x-k*(dep[x]-dep[v])等价于val[x]+=x+k*dep[v]-k*dep[x];
则我们可以用两个树状数组分别维护x+k*dep[v]和k。树状数组应支持区间修改,单点查询。最后注意下负数取模的问题。
代码:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
#include<map>
#define NI  freopen("in.txt","r",stdin);
#define NO  freopen("out.txt","w",stdout);
using namespace std;
typedef long long int ll;
typedef pair<int,int>pa;
const int N=1e6+10;
const ll mod=1e9+7;
const ll INF=1e18;
int read()
{
    int x=0;
    char ch = getchar();
    while('0'>ch||ch>'9')ch=getchar();
    while('0'<=ch&&ch<='9')
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return x;
}
/************************************************************/
struct node
{
    int to,next;
} edge[N<<2];
int n,p,cnt,id,t,x,op,v;
ll xx,k;
ll qx[N][2];
int st[N],ed[N],q[N],dep[N];
int head[N<<2];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,ll vl,int op)
{
    for(;x&&x<=n;x+=lowbit(x))
    {
        qx[x][op]+=vl;
        qx[x][op]=qx[x][op]%mod;
    }
}
ll query(int x,int op)
{
    ll res=0;
    for(;x;x-=lowbit(x))
    {
        res+=qx[x][op];
        res=res%mod;
    }
    return res%mod;
}
void init()
{
    cnt=0;
    id=0;
    memset(head,-1,sizeof(head));
    memset(qx,0,sizeof(qx));
}
void add(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void redfs(int u,int fa,int d)
{
    st[u]=++id;
    q[id]=u;
    dep[u]=d;
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].to;
        if(v!=fa)
        {
            redfs(v,u,d+1);
        }
    }
    ed[u]=id;
}
void solve(int v,ll x,ll k)
{
    int l=st[v];
    int r=ed[v];
    update(l,x+k*(ll)dep[v],0);
    update(r+1,-x-k*(ll)dep[v],0);
    update(l,k,1);
    update(r+1,-k,1);
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&x);
            add(i,x);
            add(x,i);
        }

        redfs(1,0,1);
        scanf("%d",&p);
        while(p--)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%I64d%I64d",&v,&xx,&k);
                solve(v,xx,k);
            }
            else
            {
                scanf("%d",&v);
                 ll ans=query(st[v],0)%mod-(query(st[v],1)%mod)*((ll)dep[v]%mod)%mod;
                 ans = (ans%mod+mod)%mod;
                printf("%I64d\n",ans%mod);
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值