题目链接: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. Xtrabackup 使用stream输出并压缩备份

    mysql:5.6.29xtrabackup:2.2.10mysql数据目录:/data/mysqlmysql备份目录:/data/dbbak/full #确保有足够的磁盘空间 1.安装依赖 yum ...

  2. jQuery的css

    1.css(name|pro|[,val|fn]) 访问匹配元素的样式属性. 参数name 描述: 取得第一个段落的color样式属性的值. $("p").css("co ...

  3. 原生javascript扫雷游戏

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. 有关C语言学习的调查

    有关C语言学习的调查 1.Q:你是怎么学习C语言的?(作业,实验,教材,其他),与你的高超技能相比,C语言的学习有什么经验和教训? A:之间在暑假的之后自己有买了一本C PRIME PLUS 来看基本 ...

  5. javascript 事件委托 和jQuery事件绑定on、off 和one

    一. 事件委托什么是事件委托?用现实中的理解就是:有100 个学生同时在某天中午收到快递,但这100 个学生不可能同时站在学校门口等,那么都会委托门卫去收取,然后再逐个交给学生.而在jQuery 中, ...

  6. [MFC美化] USkin使用详解-使用方法

    该种皮肤库资料很少,用法与前面几种类似. 它主要有:USkin.dll ,USkin.lib,USkin.h和Sakura.msstyles这四个文件.皮肤格式是.u3.SkinBuilder是USk ...

  7. BIEE基本函数

    一,TRIM ,去除空字符 TRIM(EXPR) SUBSTRING("UT TIME"."月份" FROM 6 FOR 2) 1.AGGREGATE AT 此 ...

  8. python连接mysql、oracle小例子

    import  MySQLdbimport  cx_Oracle   as  oraimport  pandas  as  pdfrom    sqlalchemy import create_eng ...

  9. MYSQL的一些函数

    原文地址:http://blog.sina.com.cn/s/blog_52d20fbf0100ofd5.html 1,字符串类的函数 CHARSET(str) //返回字串字符集CONCAT (st ...

  10. Lua math库

    函数名 描述 示例 结果 pi 圆周率 math.pi 3.1415926535898 abs 取绝对值 math.abs(-2012) 2012 ceil 向上取整 math.ceil(9.1) 1 ...