您的位置:首页 > 其它

CodeForces 276E Little Girl and Problem on Trees 树状数组

2016-02-27 15:34 441 查看
题意:一棵树只有一个顶点,然后由这个顶点引申出多条单链,对于输入 0 v x d,代表把距离V节点距离在d以内的所有节点增加x,对于输入 1 v,代表查询v节点的值;

解题:对根节点和根节点的所有孩子节点建一棵树状数组,树状数组下标为深度,用前缀和表示每个节点的值,在单个节点更新变化,即如在(2,5)区间加5,则位置2要+5,位置6要-5;

         然后要考虑是否跨根的情况,如果跨根就把影响直接更新到根的树状数组上,这样查询的时候就要同时查节点u的顶节点的树和根节点的树,同时更新时主要消除根节点的树和子节点的树的重复添加的情况。然后根节点的值就直接单独统计就好。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define lowbit(x) (x&(-x))

const int maxn=600000;
const int maxm=600000;
struct node
{
int u,v,next;
}edge[maxm];

//初始值都为0
struct BIT
{
vector<int>b;
int n;
void init()
{
for(int i=1;i<=n;i++)
b.push_back(0);
}
int getsum(int pos)
{
int tmp=0;
for(int i=pos; i>0; i-=lowbit(i))
tmp+=b[i-1];
return tmp;
}

int update(int pos,int val)
{
// cout<<pos<<" update "<<val<<endl;
for(int i=pos; i<=n; i+=lowbit(i))
b[i-1]+=val;//cout<<i<<" hou "<<b[i]<<endl;
}
} B[maxn];

int em;
int head[maxn];

void init()
{
em=0;
memset(head,-1,sizeof(head));
}

void addedge(int u,int v)
{
edge[em].u=u;
edge[em].v=v;
edge[em].next=head[u];
head[u]=em++;
}

int dep[maxn];
int top[maxn];

void dfs(int x,int fa,int depth,int root)
{
dep[x]=depth;
top[x]=root;
B[root].n=max(B[root].n,depth);
B[1].n=max(B[1].n,depth);
for(int i=head[x]; ~i; i=edge[i].next)
{
int v=edge[i].v;
if(v==fa) continue;
dfs(v,x,depth+1,root);
}
}
int val[10];

void update(int v,int x,int d)
{
int dis=dep[v];
//bu guo geng
int root=top[v];
if(dis>d)
{
B[root].update(dep[v]-d,x);
if(dep[v]+d+1<=B[root].n)B[root].update(dep[v]+d+1,-x);//cout<<root<<" root"<<endl;//??
}
else//guo geng
{
val[1]+=x;//geng xin geng的值
B[root].update(1,x);//cout<<root<<" root"<<endl;
if(dep[v]+d+1<=B[root].n) {B[root].update(dep[v]+d+1,-x);}//和总长度取min值
B[1].update(1,x);//cout<<1<<" root"<<endl;
// cout<<(dis-d+1)<<" "<<dis<<" "<<d<<" "<<B[1].n<<endl;
if(d-dis+1<=B[1].n) B[1].update(d-dis+1,-x);//cout<<1<<" root"<<endl;
//这里要消除自己的yingxiang
B[root].update(1,-x);
if(d-dis+1<=B[root].n) B[root].update(d-dis+1,+x);
}
}

int query(int x)
{
if(x==1) return val[1];
int dis=dep[x];
int tmp1=B[1].getsum(dis);

int tmp2=B[top[x]].getsum(dis);
// cout<<tmp1<<" query "<<tmp2<<endl;
return tmp1+tmp2;
}

int op,u,v,x,d,n,q;

void work()
{
dep[1]=0;
for(int i=1;i<=n;i++)
B[i].n=0;
memset(top,0,sizeof(top));
for(int i=head[1]; ~i; i=edge[i].next)
{
int v=edge[i].v;
dfs(v,1,1,v);
}
for(int i=1;i<=n;i++)
B[i].b.clear(),B[i].init();
// for(int i=1;i<=n;i++)
// cout<<B[i].n<<" "<<i<<endl;
for(int i=1; i<=q; i++)
{
scanf("%d",&op);
if(op==0)
{
scanf("%d%d%d",&v,&x,&d);//v d范围内加x
update(v,x,d);
}
else
{
scanf("%d",&v);
printf("%d\n",query(v));
}
}

}

//二维,树状数组维护变化,前缀和维护值

int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
init();
val[1]=0;
for(int i=1; i<=n-1; i++)
scanf("%d%d",&u,&v),addedge(u,v),addedge(v,u);
work();
// cout<<"over"<<endl;
}
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: