博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu4417
阅读量:6967 次
发布时间:2019-06-27

本文共 2548 字,大约阅读时间需要 8 分钟。

题意

给定一个数列,每次查询一个区间,和一个值h,问区间内有多少个数小于等于h。

分析

二分数的个数,划分树求解判断是否满足条件,划分树求解的是第k小的数,那么前面k个数肯定不大于这个数了,比较这个数和h即可。

code

#include
#include
#include
#include
using namespace std;typedef long long ll;const int INF = 1e9;const int MAXN = 1e5 + 5;const int LOG_N = 30;// tree[dep][i] 第dep层第i个位置的数值int tree[LOG_N][MAXN];int sorted[MAXN];// toleft[p][i] 第p层前i个数中有多少个整数分入下一层int toleft[LOG_N][MAXN];void build(int l, int r, int dep){ if(l == r) return; int mid = (l + r) / 2; int same = mid - l + 1; // 和中点数相同的数的个数 for(int i = l; i <= r; i++) if(tree[dep][i] < sorted[mid]) same--; int lpos = l, rpos = mid + 1; for(int i = l; i <= r; i++) { if(tree[dep][i] < sorted[mid]) tree[dep + 1][lpos++] = tree[dep][i]; else if(tree[dep][i] == sorted[mid] && same) { tree[dep + 1][lpos++] = tree[dep][i]; same--; } else tree[dep + 1][rpos++] = tree[dep][i]; toleft[dep][i] = toleft[dep][l - 1] + lpos - l; } build(l, mid, dep + 1); build(mid + 1, r, dep + 1);}// [L,R]里查询子区间[l,r]第k小的数int query(int L, int R, int l, int r, int dep, int k){ if(l == r) return tree[dep][l]; int mid = (L + R) / 2; // 有多少个查询区间内的节点会进入下一层的左子树 int cnt = toleft[dep][r] - toleft[dep][l - 1]; if(cnt >= k) { int newl = L + toleft[dep][l - 1] - toleft[dep][L - 1]; int newr = newl + cnt - 1; return query(L, mid, newl, newr, dep + 1, k); } else { int newr = r + toleft[dep][R] - toleft[dep][r]; int newl = newr - (r - l - cnt); return query(mid + 1, R, newl, newr, dep + 1, k - cnt); }}int n, m;int solve(int s, int t, int h){ int l = 1, r = (t - s) + 1, mid; int ans = 0; while(l <= r) { mid = (l + r) / 2; if(query(1, n, s, t, 0, mid) <= h) { ans = mid; l = mid + 1; } else r = mid - 1; } return ans;}int main(){ int T; scanf("%d", &T); for(int kase = 1; kase <= T; kase++) { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d", &sorted[i]); tree[0][i] = sorted[i]; } sort(sorted + 1, sorted + n + 1); build(1, n, 0); printf("Case %d:\n", kase); while(m--) { int s, t, h; scanf("%d%d%d", &s, &t, &h); s++; t++; printf("%d\n", solve(s, t, h)); } } return 0;}

转载于:https://www.cnblogs.com/ftae/p/6872807.html

你可能感兴趣的文章
Jmeter使用陷阱
查看>>
夏日葵电商:微信商城系统开发,分享产品运营几大细节
查看>>
ios证书--快速创建iOS证书及描述文件工具
查看>>
web前端开发前的环境搭建
查看>>
jQuery源码分析之noConflict()
查看>>
7步学会在Windows下上架iOS APP流程
查看>>
PHP使用CURL详解
查看>>
nodejs源码中的require问题
查看>>
带标签的长标题省略展示的实现
查看>>
区块链技术精华:四十种智能合约支持平台(四)
查看>>
DevOps是90%的改变和10%的技术
查看>>
Yelp研发实践:使用服务拆分单块应用
查看>>
WordPress.com使用JavaScript替换掉PHP
查看>>
代码自解释不是不写注释的理由
查看>>
Racket 6.11提供了稳定的细化类型和依赖函数特性
查看>>
Visual Studio 15改进C++工程加载
查看>>
使用 Kanban精益创新
查看>>
Deis发布1.4版本,支持Microsoft Azure
查看>>
英伟达收购Mellanox接近尾声,将成英伟达史上最大收购案
查看>>
How I Set Up OpenMP for Mac
查看>>