R - Weak Pair

HDU - 5877

离散化+权值线段树

这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k,

这么暴力的算法很自然的超时了。

然后上网搜了一下题解,感觉想的很巧妙。

就是我们要搜 子节点和父节点的乘积小于一个定值的对数。

一般求对数,有逆序对,都是把满足的放进去,到时候直接求答案就可以了。这个题目也很类似,但是还是有很大的区别的。

这个题目就是先把所有a[i] 和 k/a[i] 都放进一个数组,离散化,这一步是因为要直接求值,就是要把这个值放进线段树的这个离散化后的位置,权值为1 .

这个满足了a[i]*a[j]<=k 的要求,然后就是他们的关系必须是子节点和父节点。

这一点可以用dfs序来实现,先把父节点放进去,然后之后的子节点都可以查找这个节点,最后这个父节点的所有子节点都查找完之后就是把这个父节点弹出。

以上做法都是上网看题解的,我觉得还是没有那么难想了,这种差不多就是树上要满足是父节点子节点的关系都是可以用dfs来满足的。

其次就是弹出操作没有那么好想,最后就是放入线段树直接查找的这种建一棵权值线段树思想。

这个知道怎么写之后就很好写了,注意细节

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
#include <string>
#include <cmath>
#include <vector>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 2e5 + ;
typedef long long ll;
ll sum[maxn * ], a[maxn], b[maxn], ans;
vector<int>G[maxn];
int len, f[maxn];
bool vis[maxn];
ll n, k; void update(int id, int l, int r, int pos, int val) {
if (l == r) {
sum[id] += val;
return;
}
int mid = (l + r) >> ;
if (pos <= mid) update(id << , l, mid, pos, val);
else update(id << | , mid + , r, pos, val);
sum[id] = sum[id << ] + sum[id << | ];
} ll query(int id, int l, int r, int x, int y) {
if (x <= l && y >= r) return sum[id];
int mid = (l + r) >> ;
ll ans = ;
if (x <= mid) ans += query(id << , l, mid, x, y);
if (y > mid) ans += query(id << | , mid + , r, x, y);
return ans;
} void dfs(int u) {
vis[u] = ;
int t2 = lower_bound(b + , b + + len, a[u]) - b;
update(, , len, t2, );
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i];
if (vis[v]) continue;
int t1 = lower_bound(b + , b + + len, k / a[v]) - b;
ans += query(, , len, , t1);
dfs(v);
}
update(, , len, t2, -);
} int main() {
int t;
scanf("%d", &t);
while (t--) {
ans = ;
scanf("%lld%lld", &n, &k);
memset(vis, , sizeof(vis));
for (int i = ; i <= n; i++) scanf("%lld", &a[i]), b[i] = a[i], G[i].clear();
for (int i = ; i <= n; i++) b[i + n] = k / a[i];
sort(b + , b + + * n);
len = unique(b + , b + + * n) - b - ;
memset(sum, , sizeof(sum));
for (int i = ; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
vis[v] = ;
}
int root = ;
for (int i = ; i <= n; i++) {
if (vis[i] == ) {
root = i;
break;
}
}
memset(vis, , sizeof(vis));
dfs(root);
printf("%lld\n", ans);
}
return ;
}
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
#include <string>
#include <cmath>
#include <vector>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 2e5 + ;
typedef long long ll;
ll sum[maxn*], a[maxn], b[maxn], ans;
vector<int>G[maxn];
int len, f[maxn];
bool vis[maxn];
ll n, k;
void build(int id,int l,int r)
{
sum[id] = ;
if (l == r) return;
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
} void update(int id,int l,int r,int pos,int val)
{
if(l==r)
{
sum[id] += val;
return;
}
int mid = (l + r) >> ;
if(pos<=mid) update(id << , l, mid, pos, val);
else update(id << | , mid + , r, pos, val);
sum[id] = sum[id << ] + sum[id << | ];
} ll query(int id,int l,int r,int x,int y)
{
if (x <= l && y >= r) return sum[id];
int mid = (l + r) >> ;
ll ans = ;
if (x <= mid) ans += query(id << , l, mid, x, y);
if (y > mid) ans += query(id << | , mid + , r, x, y);
return ans;
} void dfs(int u)
{
vis[u] = ;
int t1 = lower_bound(b + , b + + len, k / a[u]) - b;
int t2 = lower_bound(b + , b + + len, a[u]) - b;
ans += query(, , len, , t1);
update(, , len, t2, );
for(int i=;i<G[u].size();i++)
{
int v = G[u][i];
if (vis[v]) continue;
dfs(v);
}
update(, , len, t2, -);
} int main()
{
int t;
scanf("%d", &t);
while(t--)
{
ans = ;
scanf("%lld%lld", &n, &k);
memset(vis, , sizeof(vis));
for (int i = ; i <= n; i++) scanf("%lld", &a[i]), b[i] = a[i], G[i].clear();
for (int i = ; i <= n; i++) b[i + n] = k / a[i];
sort(b + , b + + * n);
len = unique(b + , b + + * n) - b - ;
build(, , len);
for(int i=;i<n;i++)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
vis[v] = ;
}
int root = ;
for (int i = ; i <= n; i++) {
if (vis[i] == ) {
root = i;
break;
}
}
memset(vis, , sizeof(vis));
dfs(root);
printf("%lld\n", ans);
}
return ;
}

R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数的更多相关文章

  1. HDU 6609 离散化+权值线段树

    题意 有一个长度为\(n\)的数组W; 对于每一个\(i\)(\(1<=i<=n\)),你可以选择中任意一些元素W[k] (\(1<=k<i\)),将他们的值改变为0,使得\( ...

  2. BZOJ_3224 Tyvj 1728 普通平衡树 【离散化+权值线段树】

    一 题面 Tyvj 1728 普通平衡树 二 分析 比较明显是可以用平衡二叉搜索树(splay)做的. 用权值线段树做,前提就是要先离散化,因为权值线段树维护的值域信息. 板子. 三 AC代码 #in ...

  3. hdu 6703 array(权值线段树)

    Problem Description You are given an array a1,a2,...,an(∀i∈[1,n],1≤ai≤n). Initially, each element of ...

  4. HDU6464 (权值线段树)-(查找区间第k1小于第k2小之间的和)

    http://acm.hdu.edu.cn/showproblem.php?pid=6464 不理解先看博客:https://blog.csdn.net/g21glf/article/details/ ...

  5. S - Query on a tree HDU - 3804 线段树+dfs序

    S - Query on a tree HDU - 3804   离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...

  6. 2019年CCPC网络赛 HDU 6703 array【权值线段树】

    题目大意:给出一个n个元素的数组A,A中所有元素都是不重复的[1,n].有两种操作:1.将pos位置的元素+1e72.查询不属于[1,r]中的最小的>=k的值.强制在线. 题解因为数组中的值唯一 ...

  7. bzoj1588: [HNOI2002]营业额统计(权值线段树)

    1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 16863  Solved: 6789[Submit][Sta ...

  8. 权值线段树&线段树合并

    权值线段树 所谓权值线段树,就是一种维护值而非下标的线段树,我个人倾向于称呼它为值域线段树. 举个栗子:对于一个给定的数组,普通线段树可以维护某个子数组中数的和,而权值线段树可以维护某个区间内数组元素 ...

  9. BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)

    题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...

随机推荐

  1. nghttp2 交叉编译

    touch run.sh chmod 755 run.sh mkdir build cd build ../run.sh run.sh #!/bin/bash #cd build ../configu ...

  2. Threejs【坐标转换】如何让annotation跟随物体一起旋转

    现在根据鼠标点击的屏幕位置能够得到屏幕的坐标event.clientX和event.clientY,然后我的annotation就初始化在这个屏幕坐标的位置,那么如何绑定annotation和三维物体 ...

  3. Cocos2d-x在win7下的android交叉编译环境

    cocos2d-x在win7下的Android交叉编译环境 2014年4月14日 cocos2d-x环境配置 前面把Visual Studio+Python开发环境配好了,但还没有讲如何在Androi ...

  4. SpringBoot系列(九)单,多文件上传的正确姿势

    SpringBoot系列(九)分分钟解决文件上传 往期推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配 ...

  5. TortoiseSVN的使用,以及冲突解决办法

    接下来,试试用TortoiseSVN修改文件,添加文件,删除文件,以及如何解决冲突等. 添加文件 在检出的工作副本中添加一个Readme.txt文本文件,这时候这个文本文件会显示为没有版本控制的状态, ...

  6. 设计模式 - 模板方法模式详解及其在Spring中的应用

    基本介绍 模板方法模式(Template Method Pattern)也叫模板模式,它在一个抽象类中公开定义了执行它的方法的模板,它的字类可以按需重写方法实现,但调用将以抽象类中定义的方式进行. 简 ...

  7. 再看CVE-2018-12613 phpmyadmin后台文件包含&&RPO攻击

    写在前面 因为看了朋友的一篇分析又回头想了想自己去年遇到的这个纠结的问题. 去年写过一篇phpmyadmin后台文件包含的文章,写的非常的草草,并没有分析的过程,只是把自己的问题记了下来.当时纠结于最 ...

  8. 如何使用IE9浏览器自带开发人员工具捕获网页请求

    我们在通过浏览器访问一个网页的时候,有时候会遇到页面不能正常显示,图片不能正常加载的问题. 如果我们需要知道浏览器打开该网页时,网页中每个元素的加载情况.这时,我们便可以借助浏览器自带开发人员工具,来 ...

  9. SVM之不一样的视角

    在上一篇学习SVM中 从最大间隔角度出发,详细学习了如何用拉格朗日乘数法求解约束问题,一步步构建SVM的目标函数,这次尝试从另一个角度学习SVM. 回顾监督学习要素 数据:(\(x_i,y_i\)) ...

  10. ApiPost如何在预执行脚本里添加请求参数?

    ApiPost V3引入了预执行脚本和后执行脚本的概念,详细可以通过链接:<ApiPost的预执行脚本和后执行脚本>了解学习更多.本文主要介绍如何在预执行脚本里增加请求参数. 使用场景 我 ...