HDU 5877 dfs+ 线段树(或+树状树组)
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+ 线段树(或+树状树组)的更多相关文章
- HDU 5877 [dfs序][线段树][序]
/* 题意: n个点的树,每个点给定一个权值,给定一个k,求任意一点的子树中,权值小于k/该点权值的点共有多少个. 思路: 1.很明显的子树的操作,应用dfs序. 2.比赛的时候傻逼了,一直在调划分树 ...
- HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)
Weak Pair Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Tota ...
- hdu 5877 (dfs+树状数组) Weak Pair
题目:这里 题意: 给出一个n个结点的树和一个数k,每个结点都有一个权值,问有多少对点(u,v)满足u是v的祖先结点且二者的权值之积小于等于k. 从根结点开始dfs,假设搜的的点的权值是v,我们需要的 ...
- hdu 5692(dfs+线段树) Snacks
题目http://acm.hdu.edu.cn/showproblem.php?pid=5692 题目说每个点至多经过一次,那么就是只能一条路线走到底的意思,看到这题的格式, 多个询问多个更新, 自然 ...
- HDU 5877 Weak Pair(树状数组+dfs+离散化)
http://acm.hdu.edu.cn/showproblem.php?pid=5877 题意: 给出一棵树,每个顶点都有权值,现在要你找出满足要求的点对(u,v)数,u是v的祖先并且a[u]*a ...
- R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数
R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...
- 树形DP+树状数组 HDU 5877 Weak Pair
//树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...
- 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 ...
- Snacks HDU 5692 dfs序列+线段树
Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...
随机推荐
- HDU2546 饭卡(背包)
开始写成01背包的形式,求m元可买物品价值的最大值 dp[j] = max(dp[j], dp[j - pri[i]] + pri[i]) 结果为m - dp[m] 但后来发现是有问题的, 比如这组过 ...
- WPF中查看PDF文件
需要打开PDF文件时,我们第一印象就是使用Adobe Reader.在开发中,经常会遇到需要展示PDF文件的需求.我们会借助于Adobe Reader的Active控件来实现.不过这需要客户的机器上安 ...
- Unity3D打Box游戏
先学习一些基本的脚本实现: 1.动态创建物体.默认位置是(0,0)位置 GameObject goNew = GameObject.CreatePrimitive(PrimitiveType.Cube ...
- 外观模式/facade模式/结构型模式
外观模式 为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式三要素(client-facade-subSystem) 外观角色 ...
- sublime总结
自定义快捷键: preferences->key binding->user ctrl+d 删除行 ctrl+k 选中下一同名变量,alt+F3 选中全部同名变量 [ {"key ...
- loj1011 状态压缩
题目链接:http://lightoj.com/volume_showproblem.php?problem=1011 思路:最近的开始做dp了...很明显的一道状态压缩题,dp[n][state]表 ...
- MATLAB中stem函数用法
stem(Y) 将数据序列Y从x轴到数据值按照茎状形式画出,以圆圈终止.如果Y是一个矩阵,则将其每一列按照分隔方式画出. stem(X,Y)在X的指定点处画出数据序列Y. stem(...,'fil ...
- HashMap合并相同key的value
Map<String, String> map1 = new HashMap<>(); map1.put("x", "y"); map1 ...
- Tomcat环境配置部署测试环境及架构
Tomcat环境配置已经在前面介绍过了,这边就为童鞋们介绍下对于Tomcat的架构是怎么样的! Tomcat的架构包含(bin.conf.lib.logs.temp.wenapps.work)等文件夹 ...
- 使用Eclipse将Web项目打Jar包方法
1.对下载.安装和运行Eclipse,就不再说了: 2.找到待打包项目: 3.右键,Export-->Export: 4.选择,Jar: 5.按如图操作: 6.完成后: