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

来源:互联网 发布:windows 7 下载 iso 编辑:程序博客网 时间:2024/05/21 03:19

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
原创粉丝点击