hdu4417
hdu4417
题意
给定一个数列,每次查询一个区间,和一个值h,问区间内有多少个数小于等于h。
分析
二分数的个数,划分树求解判断是否满足条件,划分树求解的是第k小的数,那么前面k个数肯定不大于这个数了,比较这个数和h即可。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
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;
}
												
											hdu4417的更多相关文章
- hdu4417 Super Mario
		
Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability re ...
 - 主席树入门——询问区间第k大pos2104,询问区间<=k的元素个数hdu4417
		
poj2104找了个板子..,但是各种IO还可以进行优化 /* 找区间[l,r]第k大的数 */ #include<iostream> #include<cstring> #i ...
 - HDU4417 Super Mario(主席树)
		
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4417 Description Mario is world-famous plumber. ...
 - hdu4417 划分树+二分
		
//Accepted 14796 KB 453 ms //划分树 //把查询的次数m打成n,也是醉了一晚上!!! //二分l--r区间第k大的数和h比较 #include <cstdio> ...
 - HDU4417 - Super Mario(主席树)
		
题目大意 给定一个数列,每次要求你查询区间[L,R]内不超过K的数的数量 题解 和静态的区间第K大差不多,这题是<=K,先建立好n颗主席树,然后用第R颗主席树区间[1,K]内数的数量减去第L-1 ...
 - hdu4417 Super Mario 树阵离线/划分树
		
http://acm.hdu.edu.cn/showproblem.php?pid=4417 Super Mario Time Limit: 2000/1000 MS (Java/Others) ...
 - HDU--4417 Super Mario (主席树模版题)
		
题目链接 题目让求 L R区间 不大于H 的数有多少 数据太大需要离散化 #include<bits/stdc++.h> using namespace std; #define maxn ...
 - HDU4417(SummerTrainingDay08-N 主席树)
		
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
 - hdu4417(Super Mario)—— 二分+划分树
		
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
 
随机推荐
- Jquery对select下拉框的操作
			
一.jQuery获取Select选择的Text和Value:语法解释: $("#select_id").change(function(){//code...}); //为Se ...
 - Linux下deb包安装工具(附带安装搜狗输入法)
			
环境是在ubuntu14下的 #1.gdebi安装 使用deb安装工具gdebi,这个工具能解决所有依赖问题 sudo apt-get install gdebi #2.搜狗输入法 deb包下载地址: ...
 - node.js系列:(调试工具)node-inspector调试Node.js应用
			
如果你在编写Node.js代码,node-inspector是必备之选,比Node.js的内置调试器好出许多.使用起来跟Chrome的javascript调试器很相似. 使用npm安装: $ npm ...
 - KVO 模式详解
			
KVO:观察者模式.当指定的被观察对象属性被修改时,允许对象接收到通知的机制. p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; ...
 - HTML表单基本格式与代码
			
咱们先来看下今天咱们需要学习的内容,理解起来很简单,像我这种英语不好的只是需要背几个单词 在HTML中创建表单需要用到的最基本的代码和格式 <form method="post/get ...
 - xmlplus 组件设计系列之二 - 按钮
			
除了图标以外,按钮也许是最简单的组件了,现在来看看如何定义按钮组件. 使用原生按钮组件 在 xmlplus 中,HTML 元素也以组件的方式存在.所以,你可以直接通过使用 button 标签或者 in ...
 - .NET的JSON格式数据的三种转换方式
			
说明: 1..Net进行JSON格式的数据传递的时候,势必用到序列化和反序列化对象,总共有三种方式可是在.NET中实现序列化和反序列化的需求. 2.操作JSON的速度是:Json.net > M ...
 - JS基础——循环很重要
			
介绍循环之前,首先要说一下同样很重要的if-else结构,switch-case结构 ①if-else结构 if(判断条件) { 条件为true时执行 } else{ 条件为false时执行 } ②i ...
 - 【算法系列学习】SPFA邻接表最短路 [kuangbin带你飞]专题四 最短路练习 F - Wormholes
			
https://vjudge.net/contest/66569#problem/F 题意:判断图中是否存在负权回路 首先,介绍图的邻接表存储方式 数据结构:图的存储结构之邻接表 邻接表建图,类似于头 ...
 - redis 编译安装(生产环境推荐)
			
一.安装redis 1.下载redis包 wget http://download.redis.io/releases/redis-3.2.1.tar.gz 2.解压redis包到/opt下 tar ...