题目链接: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. python爬虫框架scrapy初试(二点一)

    功能:爬取某网站部分新闻列表和对应的详细内容. 列表页面http://www.zaobao.com/special/report/politic/fincrisis 实现代码: import scra ...

  2. ECMAScript6之let与const关键字

    let关键字 let关键字和var关键字一样,都是用来声明变量的,但是和var不同的是,let关键字声明的变量仅在自己的块级作用域范围内发挥作用. 我们来比较下面两段代码 var arr = new ...

  3. 百度移动搜索自动转码太坑爹,JS跳转地址会被抓取

    这段时间碰到个很崩溃的问题,一个页面通过 script 加载请求服务端进行统计再输出js进行跳转,分为两个步骤分别统计, 打开页面通过script 请求远程服务器进行统计并输出要通过js使页面跳转的最 ...

  4. 学习笔记_ADB常用指令

    ADB 查看连接到计算机的Android设备或模拟器 adb devices 说明: 正常显示状态应该是IP:Port State. State=device说明设备已经连接到计算机, State=o ...

  5. mac 搭建node 开发环境记录

    安装homebrew: enter 键 后 输入电脑密码 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/i ...

  6. springmvc注释

    //请求json串(商品信息)    输出json(商品信息) //@RequestBody将请求的商品信息的json串转成itemsCustom对象 //@ResponseBody将itemsCus ...

  7. Java:注解(Annotation)自定义注解入门

    转载地址:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的 ...

  8. 洛谷-乘积最大-NOIP2000提高组复赛

    题目描述 Description 今年是国际数学联盟确定的“2000――世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你 ...

  9. 工具类 util.Date 日期类

    /** * @description format the time * @author xf.radish * @param {String} format The format your want ...

  10. java学习开题