1、HDU 5877  Weak Pair

2、总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个

3、思路:利用dfs遍历子节点,同时对于每个子节点au,查询它有多少个祖先av满足av<=k/au。

(1)dfs+线段树

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
#define F(i,a,b) for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=,MAX=; LL k,a[N],b[N*];
int n,m,tree[N*],head[N],in[N]; //注:N*8,不是N*4,因为m可能会是n的2倍 struct Edge
{
int to,nexte;
}edge[N*]; int tot;
void AddEdge(int u,int v)
{
edge[tot].to=v;
edge[tot].nexte=head[u];
head[u]=tot++;
} void update(int pos,int l,int r,int ro,int val)
{
if(l==r){
tree[ro]+=val;
return ;
}
int mid=(l+r)>>;
if(pos<=mid)update(pos,l,mid,ro<<,val);
else update(pos,mid+,r,ro<<|,val);
tree[ro]=tree[ro<<]+tree[ro<<|];
} int query(int R,int l,int r,int ro,int L)
{
if(R>=r&&l>=L){ //注:返回条件
return tree[ro];
}
int mid=(l+r)>>;
if(R<=mid)return query(R,l,mid,ro<<,L);
else if(L>mid)return query(R,mid+,r,ro<<|,L);
else return query(mid,l,mid,ro<<,L)+query(R,mid+,r,ro<<|,mid+); //注:要拆分区间
} LL ans;
void dfs(int r)
{
int pos=lower_bound(b+,b++m,a[r])-b; //注:lower_bound(), -b不是-(b+1)
int posk=lower_bound(b+,b++m,k/a[r])-b;
ans+=1ll*query(posk,,m,,);
update(pos,,m,,);
for(int i=head[r];i!=-;i=edge[i].nexte){
dfs(edge[i].to); //利用dfs序遍历子孙
}
update(pos,,m,,-);
} int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%I64d",&n,&k);
FF(i,,n){
scanf("%I64d",&a[i]);
b[i]=a[i];
}
m=n;
FF(i,,n) b[++m]=k/a[i];
sort(b+,b++m); //排序,离散基础
m=unique(b+,b++m)-(b+); //注:unique(), -(b+1)不是-b mes(head,-);
int u,v;
mes(in,);
ans=tot=;
FF(i,,n-){
scanf("%d%d",&u,&v);
AddEdge(u,v);
in[v]++;
}
mes(tree,);
FF(i,,n){
if(!in[i]){
dfs(i);break;
}
}
printf("%I64d\n",ans);
} return ;
}

(2)dfs+树状树组

这个刚学,还不太懂

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
#define F(i,a,b) for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=,MAX=; LL k,a[N],b[N*],c[N*];
int n,m,head[N],in[N]; struct Edge
{
int to,nexte;
}edge[N*]; int tot;
void AddEdge(int u,int v)
{
edge[tot].to=v;
edge[tot].nexte=head[u];
head[u]=tot++;
} int Lowbit(int x)
{
return x&(-x);
} void update(int pos,int val)
{
for(int i=pos;i<=m;i+=Lowbit(i)){ //注
c[i]+=val;
}
} LL Sum(int posk)
{
LL ans=;
for(int i=posk;i>;i-=Lowbit(i)){ //注
ans+=c[i];
}
return ans;
} LL ans;
void dfs(int r)
{
int pos=lower_bound(b+,b++m,a[r])-b;
int posk=upper_bound(b+,b++m,k/a[r])-(b+); //注:upper_bound(),-(b+1)不是-b
ans+=Sum(posk);
update(pos,);
for(int i=head[r];i!=-;i=edge[i].nexte){
dfs(edge[i].to);
}
update(pos,-);
} int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%I64d",&n,&k);
FF(i,,n){
scanf("%I64d",&a[i]);
b[i]=a[i];
}
m=n;
FF(i,,n) b[++m]=k/a[i];
sort(b+,b++m);
m=unique(b+,b++m)-(b+); mes(head,-);
mes(c,);
int u,v;
mes(in,);
ans=tot=;
FF(i,,n-){
scanf("%d%d",&u,&v);
AddEdge(u,v);
in[v]++;
}
FF(i,,n){
if(!in[i]){
dfs(i);break;
}
}
printf("%I64d\n",ans);
} return ;
}

HDU 5877 dfs+ 线段树(或+树状树组)的更多相关文章

  1. HDU 5877 [dfs序][线段树][序]

    /* 题意: n个点的树,每个点给定一个权值,给定一个k,求任意一点的子树中,权值小于k/该点权值的点共有多少个. 思路: 1.很明显的子树的操作,应用dfs序. 2.比赛的时候傻逼了,一直在调划分树 ...

  2. HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Tota ...

  3. hdu 5877 (dfs+树状数组) Weak Pair

    题目:这里 题意: 给出一个n个结点的树和一个数k,每个结点都有一个权值,问有多少对点(u,v)满足u是v的祖先结点且二者的权值之积小于等于k. 从根结点开始dfs,假设搜的的点的权值是v,我们需要的 ...

  4. hdu 5692(dfs+线段树) Snacks

    题目http://acm.hdu.edu.cn/showproblem.php?pid=5692 题目说每个点至多经过一次,那么就是只能一条路线走到底的意思,看到这题的格式, 多个询问多个更新, 自然 ...

  5. HDU 5877 Weak Pair(树状数组+dfs+离散化)

    http://acm.hdu.edu.cn/showproblem.php?pid=5877 题意: 给出一棵树,每个顶点都有权值,现在要你找出满足要求的点对(u,v)数,u是v的祖先并且a[u]*a ...

  6. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

  7. 树形DP+树状数组 HDU 5877 Weak Pair

    //树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...

  8. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  9. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

随机推荐

  1. wp8 入门到精通 数据库更新字段(一)

    public class UserInfoDB : BaseDB { public UserInfoDB() : base(@"Data Source=isostore:\MakeLove\ ...

  2. view的setTag() 和 getTag()应用 (转)

    原文地址:http://www.cnblogs.com/qingblog/archive/2012/07/03/2575140.html View中的setTag(Onbect)表示给View添加一个 ...

  3. java中的负数的问题

    在计算机中是使用二制数中的最高位表示来正负. 二进制的储存中都是用的补码,正数的原码.反码和补码相同,负数的原码是最高位为1,反码最高位不变,其余各位取反,补码为其反码+1(重要!!) 首先得知道最高 ...

  4. MySQL5.7中新增的JSON类型的使用方法

    创建表json_test: CREATE TABLE json_test(id INT(11) AUTO_INCREMENT PRIMARY KEY,person_desc JSON)ENGINE I ...

  5. JMeter中的关联-正则表达式提取(1)

    运用Jmeter正则提取器,可以从请求的响应结果中取到需要的内容,从而实现关联. jmeter之关联 的个人理解: 关联是请求与请求之间存在数据依赖关系,需要从上一个请求获取下一个请求需要回传回去的数 ...

  6. 基于netty的微服务架构

    基于netty的微服务架构 微服务一篇好文章 http://san-yun.iteye.com/blog/1693759 教程 http://udn.yyuap.com/doc/essential-n ...

  7. BeanShell用法汇总(部分摘抄至网络)【转】

    说明:本文部分资料摘抄至 来源: http://www.cnblogs.com/puresoul/p/4915350.html 来源: http://www.cnblogs.com/puresoul/ ...

  8. CSS 样式使用

    [attribute] 用于选取带有指定属性的元素. [attribute=value] 用于选取带有指定属性和值的元素. [attribute~=value] 用于选取属性值中包含指定词汇的元素. ...

  9. Manthan, Codefest 16

    暴力 A - Ebony and Ivory import java.util.*; import java.io.*; public class Main { public static void ...

  10. Codeforces Round #343 (Div. 2)

    居然补完了 组合 A - Far Relative’s Birthday Cake import java.util.*; import java.io.*; public class Main { ...