题目链接: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. WHAT?【 $.fn.extend() 】vs【 $.extend() 】

    废话不多说,干货来了,转自http://www.cnblogs.com/hellman/p/4349777.html (function($){ $.fn.extend({ test:function ...

  2. 微信小程序前置课程:Flex 布局教程(一):语法篇

    原文:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool 网页布局(layout)是CSS的一个重点 ...

  3. CodeForces 676D Theseus and labyrinth

    最短路. $dis[i][j][k]$记录到点$(i,j)$,门的状态为$k$时的最短路.转移的时候有$8$种方案,即直接走向周围四个点,或者进行旋转.比较烦的是判断两个相邻的点在状态$k$下是否连通 ...

  4. 去掉UItableview section headerview黏性

    UITabelView在style为plain时,在上拉是section始终粘在最顶上而不是跟随滚动而消失或者出现 可以通过设置UIEdgeInsetsMake: - (void)scrollView ...

  5. string 数字序列大小比较

    string 数字序列大小比较 string.compare string a = "022"; string b="1"; 比较结果 '022' < ' ...

  6. python numpy基础 数组和矢量计算

    在python 中有时候我们用数组操作数据可以极大的提升数据的处理效率, 类似于R的向量化操作,是的数据的操作趋于简单化,在python 中是使用numpy模块可以进行数组和矢量计算. 下面来看下简单 ...

  7. Jmeter连接SqlServer数据库进行压力测试

    Jmeter连接SqlServer数据库进行压力测试 前提准备:先安装jdbc驱动 驱动下载链接地址:http://pan.baidu.com/s/1bpDpjSr 密码:v6tn 下载解压之后,讲s ...

  8. [O]打印时闪退问题

    1. 使用的是Office批量打印精灵1.2版,软件可以打开 2. Win8.1 MSDN原版操作系统,系统重装了,.NET Framework也装了 3. 使用真实打印机打印,打印时闪退,没有任何提 ...

  9. 杭州蓝松科技推出的安卓端的USB转串口调试助手, 欢迎下载使用

    杭州蓝松科技推出的安卓端的USB转串口调试助手, 欢迎下载使用 下载地址:http://files.cnblogs.com/guobaPlayer/%E8%93%9D%E6%9D%BEUSB%E4%B ...

  10. ubuntu enable all Ubuntu software (main universe restricted multiverse) repositories use

    sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc) main universe ...