树分治,设当前树的分治中心为x,其子树分治中心为y,则设father[y]=x,分治下去则可以得到一颗重心树,而且树的深度是logn。

  询问操作(x,d),只需要查询重心树上x到重心树根节点上的节点的累加和。假设当前节点是y,那么节点y可以贡献的答案是那些以y为分治中心且到y距离为d-dis(x,y)的节点的总和。当然这样可能会出现重复的情况,重复情况只会出现在包含x的那颗子树上,因此减掉即可。修改操作类似。复杂度O(nlognlogn)

代码

#include<cstdio>
#include<cstring>
#define N 200010
#define LL long long
using namespace std;
int dp,pre[N],p[N],tt[N],vis[N],father[N],s[N],tmp,m;
int n,a,b,i,w[N],L,cnt,tot,len[N],Len[N],start[N],Start[N],v[N];
int deep[N],ss[N][21],fa[N];
int c[N*50];
int min(int a,int b)
{
if (a<b) return a;return b;
}
int lowbit(int x)
{
return x&(-x);
}
void cc(int x,int w,int y)
{
while (x<=L)
{
c[y+x]+=w;
x+=lowbit(x);
}
}
LL sum(int x,int y)
{
LL ans=0;
while (x>0)
{
ans+=c[y+x];
x-=lowbit(x);
}
return ans;
}
void link(int x,int y)
{
dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
}
void gao(int x)
{
int i;
i=p[x];
while (i)
{
if (tt[i]!=fa[x])
{
fa[tt[i]]=x;
deep[tt[i]]=deep[x]+1;
gao(tt[i]);
}
i=pre[i];
}
}
int lca(int x,int y)
{
if(deep[x]>deep[y])x^=y^=x^=y;
int i;
for(i=19;i>=0;i--)
{
if(deep[y]-deep[x]>=(1<<i))
{
y=ss[y][i];
}
}
if(x==y)return x;
for(i=19;i>=0;i--)
{
if(ss[x][i]!=ss[y][i])
{
x=ss[x][i];
y=ss[y][i];
}
}
return fa[x];
}
void getroot(int x,int fa,int sum)
{
int i,flag=0;
i=p[x];s[x]=1;
while (i)
{
if ((!vis[tt[i]])&&(tt[i]!=fa))
{
getroot(tt[i],x,sum);
s[x]+=s[tt[i]];
if (s[tt[i]]>sum/2) flag=1;
}
i=pre[i];
}
if (sum-s[x]>sum/2) flag=1;
if (!flag) tmp=x;
}
void dfs(int x,int fa,int dis)
{
int i;
i=p[x];
if (dis>cnt) cnt=dis;
v[dis]+=w[x];
while (i)
{
if ((!vis[tt[i]])&&(tt[i]!=fa))
dfs(tt[i],x,dis+1);
i=pre[i];
}
}
void clear()
{
int i;
for (i=1;i<=cnt;i++)
v[i]=0;cnt=0;
}
int work(int x,int fa,int sum)
{
int i,root,t;
getroot(x,0,sum);
root=tmp;
father[root]=fa;
i=p[root];
vis[root]=1;
while (i)
{
if (!vis[tt[i]])
{
if (s[root]>s[tt[i]])
t=work(tt[i],root,s[tt[i]]);
else
t=work(tt[i],root,sum-s[root]);
//------dist(root,point in subtree t)-------- dfs(tt[i],0,2);
Len[t]=cnt;
Start[t]=tot;
for (int j=1;j<=cnt;j++)
{
L=cnt;
cc(j,v[j],Start[t]);
}
tot+=cnt;
clear(); }
i=pre[i];
}
vis[root]=0; //--------dist(root,all point)---------- dfs(root,0,1);
len[root]=cnt;
start[root]=tot;
for (i=1;i<=cnt;i++)
{
L=cnt;
cc(i,v[i],start[root]);
}
tot+=cnt;
clear(); return root;
}
LL query(int x,int d)
{
int y=0,z=x,t;
LL ans=0;
while (x)
{
t=lca(x,z);
t=deep[x]+deep[z]-2*deep[t];
L=len[x];
ans+=sum(min(L,d-t+1),start[x]); if (y)
{
L=Len[y];
ans-=sum(min(L,d-t+1),Start[y]);
}
y=x;
x=father[x];
}
return ans;
}
void change(int x,int w)
{
int y=0,z=x,t;
while (x)
{
t=lca(x,z);
t=deep[x]+deep[z]-2*deep[t];
L=len[x];
cc(t+1,w,start[x]); if (y)
{
L=Len[y];
cc(t+1,w,Start[y]);
}
y=x;
x=father[x];
}
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
dp=0;memset(p,0,sizeof(p));
for (i=1;i<=tot;i++)
c[i]=0;tot=0; for (i=1;i<=n;i++)
scanf("%d",&w[i]);
for (i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
link(a,b);
link(b,a);
}
gao(1);
for(i=1;i<=n;i++)
ss[i][0]=fa[i];
for(int h=1;h<20;h++)
{
for(i=1;i<=n;i++)
{
ss[i][h]=ss[ss[i][h-1]][h-1];
}
}
work(1,0,n); for (i=1;i<=m;i++)
{
getchar();
char ch;
scanf("%c%d%d",&ch,&a,&b);
if (ch=='?')
printf("%I64d\n",query(a,b));
else
{
change(a,b-w[a]);
w[a]=b;
}
} }
}

  

hdu4918 Query on the subtree的更多相关文章

  1. HDU4918 Query on the subtree 点分治+树状数组

    bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n. At the very begining, the i-th ...

  2. HDU 4918 Query on the subtree(动态点分治+树状数组)

    题意 给定一棵 \(n\) 个节点的树,每个节点有点权.完成 \(q\) 个操作--操作分两种:修改点 \(x\) 的点权.查询与 \(x\) 距离小于等于 \(d\) 的权值总和. \(1 \leq ...

  3. ZOJ 3686 A Simple Tree Problem

    A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a rooted tree, each no ...

  4. Sphinx 2.2.11-release reference manual

    1. Introduction 1.1. About 1.2. Sphinx features 1.3. Where to get Sphinx 1.4. License 1.5. Credits 1 ...

  5. zoj3686(线段树的区间更新)

    对线段树的区间更新有了初步的了解... A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a ...

  6. ZOJ 3686 A Simple Tree Problem(线段树)

    Description Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the ...

  7. Random Numbers Gym - 101466K dfs序+线段树

    Tamref love random numbers, but he hates recurrent relations, Tamref thinks that mainstream random g ...

  8. BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】

    A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...

  9. xtu数据结构 I. A Simple Tree Problem

    I. A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB 64-bit integer IO format: %lld     ...

随机推荐

  1. Lambda中的一些方法的总结

    public List<UserInfoBaseModel> GetNameByIDList(List<int> UserID) { var UserList = LoadRe ...

  2. angularjs select 循环中出现第一个 option 为空格问题

    当select 的ng-module 为空时, select显示空白行. 解决:指定ng-module的默认值.

  3. win7下vs2010编译生成sqlite3.dll库

    http://blog.csdn.net/qing666888/article/details/53582262 http://download.csdn.net/detail/qing666888/ ...

  4. Compiling Inkscape on Windows

    http://wiki.inkscape.org/wiki/index.php/Compiling_Inkscape_on_Windows http://www.oschina.net/news/80 ...

  5. zepto源码--qsa--学习笔记

    zepto内部选择器qsa方法的实现. 简述实现原理: 通过判断传入的参数类型: 如果是'#id',则使用getElementById(id)来获取元素,并且将结果包装成数组形式: 如果是'.clas ...

  6. PHP--浏览器禁用cookie后,怎么使用session

    sessionid是存储在cookie中的,解决方案如下: Session URL重写,保证在客户端禁用或不支持COOKIE时,仍然可以使用Session session机制.session机制是一种 ...

  7. php--求几个数中的最小值

    <?phpecho min(2, 3, 1, 6, 7);  // 1echo min(array(2, 4, 5)); // 2echo min(0, 'hello');     // 0ec ...

  8. 消息队列系列(一):.Net平台下的消息队列介绍

    本系列主要记录最近学习消息队列的一些心得体会,打算形成一个系列文档.开篇主要介绍一下.Net平台下一些主流的消息队列框架.       RabbitMQ:http://www.rabbitmq.com ...

  9. 错误提示: An App ID with identifier "*****" is not avaliable. Please enter a different string.

    百度了很多,但大多的解决办法就是 更改BundleID,的确管用,,但是有的情况下,你需要跟同事合作,公用同一个BundleID, 我是这样处理的:工具栏中打开Window—project删除所有工程 ...

  10. Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. For example: Given the below binary tree andsum =

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...