CodeForces 396C

来源:互联网 发布:java plug in是什么 编辑:程序博客网 时间:2024/06/14 16:28

题目大意:

   给出一棵以1为根的树,形式是从节点2开始给出每个节点的父亲节点;然后是m次操作,操作分为两种,1 v, x, k,表示在以v为根的字数上添加,添加的法则是看这个节点与v节点的距离为i的话,加上x-i*k;2 v查询节点v的值。

解题方法:

   一颗树不好解决,dfs一下,将树形转化为线性。

   按在题目要求对于1操作,我们将区域内所有的点都加上x+dep【v】*k

               对于2操作,我们对于求出来的点数值减去dep【v】*k。

   如何求见修改呢?

   add(l,v),add(r+1,-v)就ok了

我的代码:

#include <cstdio>#include <iostream>#include <algorithm>#include <vector>#include <cstring>#define maxn 1000000#define MOD 1000000007using namespace std;int n,m,dep[maxn];vector <int> po[maxn];int l[maxn],r[maxn],totl;int dfs(int v,int fa){  //cout<<v<<endl;  l[v]=totl++;  if (v==1) dep[v]=1;  else dep[v]=dep[fa]+1;  for (int i=0;i<po[v].size();i++)    dfs(po[v][i],v);  r[v]=totl-1;  return 0;}long long tree1[maxn],tree2[maxn];int add1(int x,long long v){  for (int i=x;i<=n;i+=i&(-i))    tree1[i]=(tree1[i]+v)%MOD;  return 0;}int add2(int x,int v){  for (int i=x;i<=n;i+=i&(-i))    tree2[i]=(tree2[i]+v)%MOD;  return 0;}long long sum(int x){  long long a=0,b=0;  for (int i=l[x];i>0;i-=i&(-i)){    a+=tree1[i];    b+=tree2[i];  }  return ((a-b*dep[x])%MOD+MOD)%MOD;}int main (){  //freopen("test.in","r",stdin);  while (~scanf("%d",&n)){    memset(dep,0,sizeof(dep));    memset(tree1,0,sizeof(tree1));    memset(tree2,0,sizeof(tree2));    for (int i=1;i<=n;i++) po[i].clear();    for (int i=2;i<=n;i++){        int a;scanf("%d",&a);        po[a].push_back(i);    }    totl=1;dfs(1,0);    scanf("%d",&m);    for (int i=1;i<=m;i++){        int op,v;scanf("%d%d",&op,&v);        if (op==1){            long long x,k;            cin>>x>>k;            add1(l[v],(x+dep[v]*k));            add1(r[v]+1,-(x+dep[v]*k));            add2(l[v],k);            add2(r[v]+1,-k);        }        else {            cout<<sum(v)<<endl;        }    }  }  return 0;}


0 0
原创粉丝点击