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. 用CocoaPods做iOS程序的依赖管理(转摘)

    转摘自:http://blog.devtang.com/blog/2014/05/25/use-cocoapod-to-manage-ios-lib-dependency/ 文档更新说明 2012-1 ...

  2. Hibernate 和 快照

    Hibernate我们已经学了四天,该讲的知识我们已经讲完,明天放假,后天练习一天就要结束hibernate的学习,有点不舍的,想来hibernate也不是传说中的那么难,在次将hibernate中三 ...

  3. Linux之find命令用于统计信息

    1. 计算当前目录中的文件数: [root@localhost tmp]# find . -type f | wc -l 2. 查找/etc目录中最新的和最旧的文件,以文件时间排序并按年-月-日的格式 ...

  4. BNUOJ1067生成函数入门

    https://www.bnuoj.com/v3/problem_show.php?pid=1067

  5. Java反射详解及应用示例

    反射是Java中最重要的内容之一,了解反射原理对我们学习各种框架具有很大的帮助 反射的原理: 反射应用示例: import java.lang.reflect.Constructor; import ...

  6. 软件开发中的完整测试所包括的环节UT、IT、ST、UAT

    软件开发中的完成测试环境所包括的环节包括:UT.IT.ST.UAT UT = Unit Test 单元测试 IT = System Integration Test 集成测试ST = System T ...

  7. codeforces 286 div2 B

    思路:质因子累乘的值即为所求#include<iostream> #include<algorithm> #include<stdio.h> #include< ...

  8. AOP动态代理解析4-代理的创建

    做完了增强器的获取后就可以进行代理的创建了 AnnotationAwareAspectJAutoProxyCreator->postProcessAfterInitialization-> ...

  9. Codeforces Round #355 (Div. 2)-B

    B. Vanya and Food Processor 题目链接:http://codeforces.com/contest/677/problem/B Vanya smashes potato in ...

  10. Codeforces Round #334 (Div. 2)

    水 A - Uncowed Forces #include <bits/stdc++.h> using namespace std; typedef long long ll; const ...