hdu4918 Query on the subtree
树分治,设当前树的分治中心为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的更多相关文章
- 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 ...
- HDU 4918 Query on the subtree(动态点分治+树状数组)
题意 给定一棵 \(n\) 个节点的树,每个节点有点权.完成 \(q\) 个操作--操作分两种:修改点 \(x\) 的点权.查询与 \(x\) 距离小于等于 \(d\) 的权值总和. \(1 \leq ...
- ZOJ 3686 A Simple Tree Problem
A Simple Tree Problem Time Limit: 3 Seconds Memory Limit: 65536 KB Given a rooted tree, each no ...
- 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 ...
- zoj3686(线段树的区间更新)
对线段树的区间更新有了初步的了解... A Simple Tree Problem Time Limit: 3 Seconds Memory Limit: 65536 KB Given a ...
- 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 ...
- Random Numbers Gym - 101466K dfs序+线段树
Tamref love random numbers, but he hates recurrent relations, Tamref thinks that mainstream random g ...
- BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】
A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...
- xtu数据结构 I. A Simple Tree Problem
I. A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB 64-bit integer IO format: %lld ...
随机推荐
- install zabbix-agent on CENTOS
in ubuntu--https://www.digitalocean.com/community/tutorials/how-to-install-zabbix-on-ubuntu-configur ...
- yaf在windows7下32位的安装教程
首先下载php_yaf.dll文件http://pecl.php.net/package/yaf/2.2.9/windows 打开扩展extension=php_yaf.dll 然后下载工具 http ...
- UDF
一:UDF 1.自定义UDF 二:UDAF 2.UDAF 3.介绍AbstractGenericUDAFResolver 4.介绍GenericUDAFEvaluator 5.程序 package o ...
- copy构造函数的秘密
1.先来看这段代码: MyString::MyString(){ this->mstr = NULL;} MyString::MyString(MyString &str){ //用一个 ...
- java不常用语法汇总(jdk1.6)
1.浮点数省略的0 System.out.println(.5f); //.5和0.5等价. 2.import static引入一个static method后,可以在这个类中直接使用这个method ...
- Microsoft Dynamics AX 2009 White Paper: Close Non-Financial Transfers
http://www.microsoft.com/en-us/download/confirmation.aspx?id=12174
- js - 驼峰命名
1. // 驼峰命名 console.log(hump('border-bottom-color')) function hump( str) { if (typeof str != 'string' ...
- 通过iphone蓝牙与经过苹果MFI授权认证的硬件通讯,传输图片(转)
http://blog.csdn.net/hwj2012/article/details/7883711 相关: http://blog.csdn.net/xufeidll/article/detai ...
- ionic一些常见问题及方法
1.打包的app无法访问互联网及网络资源(比如网页调试可以请求数据,安装到手机上无法请求数据) 添加白名单插件 ionic plugin add https://github.com/apache/c ...
- loop_nslookup
function loop_nslookup() { $baseFolder = "D:\ps_toolkit" $ip_list = "$baseFolder\ip_l ...