树分治,设当前树的分治中心为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. nginx博客系统(内含nginx图片缩略图处理代码,不错)

    一直以来都在Qzone.CSDN等上面写博客,偶尔有些想法就在Paas平台上搭建服务,新浪和曾经的google上都用过其appengine.可是在别人的平台上写东西,总归有些不方便,有受制于人的感觉. ...

  2. mssql 常用SQL语句或函数

    按 OrderDate 的顺序计算 SalesOrderHeader 表中所有行的行号,并只返回行 50 到 60(含). WITH OrderedOrders AS ( SELECT SalesOr ...

  3. C++ 简单 Hash容器的实现

    主要实现了以整数为关键字的hash,以key%m_nSize为哈希函数,以(hash(key)+i)%m_nSize重新寻址,并附带了elf_hash的实现,使用过程中可灵活修改. #ifndef _ ...

  4. Magento多语言功能

    Magento多语言功能是建立在视图(view)基础之上的,可以通过后台创建店铺视图来创建基于Magento的多语言店铺.本文为大家讲解如何创建多语言的功能.首先,进入“管理店铺”节点,如下所示. S ...

  5. [LeetCode]题解(python):033-Search in Rotated Sorted Array

    题目来源 https://leetcode.com/problems/search-in-rotated-sorted-array/ Suppose a sorted array is rotated ...

  6. A Guide to Creating a Quality Project Schedule

    Successful projects start with a good quality project schedule. Creating a schedule is one of the fi ...

  7. 开始了ecshop

    一个多星期前开始接触ecshop,突然决定要用它来做网站,于是从网上找各种手册与视频,联系官网客服,然后知道官网一共提供三种类型的服务,一种是ecshop授权,不包含任何技术支持,第二种是易开店的标准 ...

  8. POI对Excel

    完美兼容excel2003 和excel2007的读取,处理了所有excel所有的类型,依赖包如下: poi-3.10-FNAL.jar poi-ooxml-3.10-FNAL.jar poi-oox ...

  9. linux命令之tee

    功能说明:读取标准输入的数据,并将其内容输出成文件.语 法:tee [-ai][--help][--version][文件...]补充说明:tee指令会从标准输入设备读取数据,将其内容输出到标准输出设 ...

  10. 深入css中的margin

    深入css中的margin 第一:margin-top css代码(元素没有任何定位的情况下,并且元素默认为block) <style type="text/css"> ...