题目链接:hdu_5314_Happy King

题意:

给出一颗n个结点的树,点上有权值;

求点对(x,y)满足x!=y且x到y的路径上最大值与最小值的差<=D;

题解:

还是树的点分治,在统计答案的时候先按到根的最小值排序,然后用最大值减D去找有多少个满足答案。

 #include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef pair<int,int>P;
typedef long long ll;
const int N=1e5+; int n,k,g[N],v[N*],nxt[N*],ed,w[N],t;
int vis[N],size[N],mx[N],mi,tot,root;
P dis[N];
ll ret; inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
void init(){F(i,,n)g[i]=,vis[i]=;ed=,ret=;} void dfs_size(int u,int fa)
{
size[u]=,mx[u]=;
for(int i=g[u];i;i=nxt[i])
if(v[i]!=fa&&!vis[v[i]])
{
dfs_size(v[i],u),size[u]+=size[v[i]];
if(size[v[i]]>mx[u])mx[u]=size[v[i]];
}
} void dfs_root(int r,int u,int fa)
{
if(size[r]-size[u]>mx[u])mx[u]=size[r]-size[u];
if(mx[u]<mi)mi=mx[u],root=u;
for(int i=g[u];i;i=nxt[i])
if(v[i]!=fa&&!vis[v[i]])
dfs_root(r,v[i],u);
} void dfs_dis(int u,int mi,int mx,int fa)
{
mi=min(mi,w[u]),mx=max(mx,w[u]);
if(mx<=mi+k)dis[++tot]=P(mi,mx);
for(int i=g[u];i;i=nxt[i])
if(v[i]!=fa&&!vis[v[i]])
dfs_dis(v[i],mi,mx,u);
} ll calc(int u,int mi,int mx)
{
ll ans=;
tot=,dfs_dis(u,mi,mx,);
sort(dis+,dis+tot+);
F(i,,tot)
{
int p=lower_bound(dis+,dis+i+,P(dis[i].second-k,))-dis;
ans+=i-p;
}
return ans;
} void dfs(int u=)
{
mi=n,dfs_size(u,);
dfs_root(u,u,);
ret+=calc(root,w[root],w[root]),vis[root]=;
for(int i=g[root];i;i=nxt[i])
if(!vis[v[i]])ret-=calc(v[i],w[root],w[root]);
for(int i=g[root];i;i=nxt[i])
if(!vis[v[i]])dfs(v[i]);
} int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
init();
F(i,,n)scanf("%d",w+i);
F(i,,n-)
{
int x,y;
scanf("%d%d",&x,&y);
adg(x,y),adg(y,x);
}
dfs(),printf("%lld\n",ret*);
}
return ;
}

法2:

将统计的答案按倒根的最大值排序,如果当前最大值为这个点的最大值,那么我们就在树状数组中去找最大值-D的答案,所以我们在统计好后需要将这个点的最小值插入树状数组

 #include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef pair<int,int>P;
typedef long long ll;
const int N=1e5+; int n,k,g[N],v[N*],nxt[N*],ed,w[N],t,hsh[N],hsh_ed;
int vis[N],size[N],mx[N],mi,tot,root,sum[N];
P dis[N];ll ans; inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
void init(){F(i,,n)g[i]=,vis[i]=;ed=ans=,hsh_ed=;} inline void add(int x,int c){while(x<=hsh_ed+)sum[x]+=c,x+=x&-x;}
inline int ask(int x){int an=;while(x>)an+=sum[x],x-=x&-x;return an;}
inline int getid(int x){return lower_bound(hsh+,hsh++hsh_ed,x)-hsh;}
void dfs_size(int u,int fa)
{
size[u]=,mx[u]=;
for(int i=g[u];i;i=nxt[i])
if(v[i]!=fa&&!vis[v[i]])
{
dfs_size(v[i],u),size[u]+=size[v[i]];
if(size[v[i]]>mx[u])mx[u]=size[v[i]];
}
} void dfs_root(int r,int u,int fa)
{
if(size[r]-size[u]>mx[u])mx[u]=size[r]-size[u];
if(mx[u]<mi)mi=mx[u],root=u;
for(int i=g[u];i;i=nxt[i])
if(v[i]!=fa&&!vis[v[i]])
dfs_root(r,v[i],u);
} void dfs_dis(int u,int mi,int mx,int fa)
{
mi=min(mi,w[u]),mx=max(mx,w[u]);
if(mx<=mi+k)dis[++tot]=P(mx,mi);
for(int i=g[u];i;i=nxt[i])
if(v[i]!=fa&&!vis[v[i]])
dfs_dis(v[i],mi,mx,u);
} ll calc(int u,int mi,int mx)
{
ll ans=;
tot=,dfs_dis(u,mi,mx,);
sort(dis+,dis++tot);
F(i,,tot)
{
ans+=ask(hsh_ed)-ask(getid(dis[i].first-k)-);
add(getid(dis[i].second),);
}
F(i,,tot)add(getid(dis[i].second),-);
return ans;
} void dfs(int u=)
{
mi=n,dfs_size(u,);
dfs_root(u,u,);
ans+=calc(root,w[root],w[root]),vis[root]=;
for(int i=g[root];i;i=nxt[i])
if(!vis[v[i]])
ans-=calc(v[i],w[root],w[root]);
for(int i=g[root];i;i=nxt[i])
if(!vis[v[i]])dfs(v[i]);
} int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
init();
F(i,,n)scanf("%d",w+i),hsh[i]=w[i];
F(i,,n-)
{
int x,y;
scanf("%d%d",&x,&y);
adg(x,y),adg(y,x);
}
sort(hsh+,hsh++n),hsh_ed=unique(hsh+,hsh++n)-hsh;
dfs(),printf("%lld\n",ans*);
}
return ;
}

hdu_5314_Happy King(树的点分治)的更多相关文章

  1. HDU4812 D Tree(树的点分治)

    题目大概说给一棵有点权的树,输出字典序最小的点对,使这两点间路径上点权的乘积模1000003的结果为k. 树的点分治搞了.因为是点权过根的两条路径的LCA会被重复统计,而注意到1000003是质数,所 ...

  2. CF 322E - Ciel the Commander 树的点分治

    树链剖分可以看成是树的边分治,什么是点分治呢? CF322E - Ciel the Commander 题目:给出一棵树,对于每个节点有一个等级(A-Z,A最高),如果两个不同的节点有相同等级的父节点 ...

  3. hdu 4670 树的点分治

    思路:首先当然是要用树的点分治了.根节点为root,那么经过root的合法路径数求出来这题就解决了.因为我们可以用分治枚举根,最后将所有根的路径数加起来就是结果.当然这里的根不是整棵树的根,是子树根. ...

  4. bzoj 3435: [Wc2014]紫荆花之恋 替罪羊树维护点分治 && AC400

    3435: [Wc2014]紫荆花之恋 Time Limit: 240 Sec  Memory Limit: 512 MBSubmit: 159  Solved: 40[Submit][Status] ...

  5. bzoj 2152: 聪聪可可 树的点分治

    2152: 聪聪可可 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 485  Solved: 251[Submit][Status] Descripti ...

  6. hdu 4812 D Tree(树的点分治)

    D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...

  7. POJ 1741/1987 树的点分治

    树的点分治,主要思想是每次找子树的重心,计算经过根节点的情况数,再减去点对属于同一子树的情况. #include <iostream> #include <vector> #i ...

  8. poj 1741 树的点分治(入门)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18205   Accepted: 5951 Description ...

  9. 【poj1741】Tree 树的点分治

    题目描述 Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dis ...

随机推荐

  1. R和python连接SQL sever 数据库操作

    在R的使用中,为了方便提取数据, 我们经常要进行数据库进行操作,接下来我们尝试使用R进行连接数据. 这里我们使用R中的RODBC进行操作, 首先,我们需要先配置ODBC资源管理器 通过任务管理器或者w ...

  2. database disk image is malformed

    在Linux上使用yum安装软件的时候报如下错误: database disk image is malformed 根本原因是:yum的缓存出错, 需要清理缓存 使用如下命令来解决这个问题: yum ...

  3. Linux学习初步

    centOS 6.5关闭防火墙步骤  关闭命令:  service iptables stop         永久关闭防火墙:chkconfig iptables off两个命令同时运行,运行完成后 ...

  4. bat脚本-set(setlocal enabledelayedexpansion) 学习

    设置本地为延迟扩展.其实也就是:延迟变量,全称延迟环境变量扩展. 事件一: @echo off set a=4 set a=5&echo %a% pause 解说:为什么是4而不是5呢?在ec ...

  5. 谷歌游览器对<input type='file'> change只能响应1次解决和样式的改变

    在项目过程中遇到的需要上传本地文件,file的原始控件不太美观,但是这个控件和button有点不太一样, 改变这个样式的思路就是在控件外面套一层链接,然后把file控件的透明度设置为0(透明).样式只 ...

  6. apk反编译查看源码

    1.将apk解压

  7. 基于html5 canvas 的强大图表插件【Chart.js】

    名词解释 Chart.js:是基于html5和canvas的强大图表插件,支持多样的图表形式,柱状线性饼环极地雷达等等: canvas:只兼容到IE9 excanvas.js:强大的第三方兼容插件,可 ...

  8. CentOS 7将Python 2.X.X升级到Python 3.X.X

    # cd /usr/local/src/ # ls Python-.tgz # .tgz # ls Python- Python-.tgz # cd Python-/ # yum install gc ...

  9. LeetCode 319. Bulb Switcher

    There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off every ...

  10. 前端用Request Payload方式请求后台

    后台接收方式: InputStream inputStream = request.getInputStream(); byte[] buff = new byte[1024]; int len = ...