您的位置:首页 > 其它

CodeForces 396C

2014-08-20 11:42 204 查看
题目大意:

   给出一棵以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 1000000007
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: