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的更多相关文章

  1. hdu4417 Super Mario

    Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability re ...

  2. 主席树入门——询问区间第k大pos2104,询问区间<=k的元素个数hdu4417

    poj2104找了个板子..,但是各种IO还可以进行优化 /* 找区间[l,r]第k大的数 */ #include<iostream> #include<cstring> #i ...

  3. HDU4417 Super Mario(主席树)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4417 Description Mario is world-famous plumber. ...

  4. hdu4417 划分树+二分

    //Accepted 14796 KB 453 ms //划分树 //把查询的次数m打成n,也是醉了一晚上!!! //二分l--r区间第k大的数和h比较 #include <cstdio> ...

  5. HDU4417 - Super Mario(主席树)

    题目大意 给定一个数列,每次要求你查询区间[L,R]内不超过K的数的数量 题解 和静态的区间第K大差不多,这题是<=K,先建立好n颗主席树,然后用第R颗主席树区间[1,K]内数的数量减去第L-1 ...

  6. hdu4417 Super Mario 树阵离线/划分树

    http://acm.hdu.edu.cn/showproblem.php?pid=4417 Super Mario Time Limit: 2000/1000 MS (Java/Others)    ...

  7. HDU--4417 Super Mario (主席树模版题)

    题目链接 题目让求 L R区间 不大于H 的数有多少 数据太大需要离散化 #include<bits/stdc++.h> using namespace std; #define maxn ...

  8. HDU4417(SummerTrainingDay08-N 主席树)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. hdu4417(Super Mario)—— 二分+划分树

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

随机推荐

  1. Object类型知识总结,你掌握了多少?

      Object类型    ECMAScript中的对象其实就是一组数据和功能的集合.对象可以通过执行new操作符后跟要创建的对象类型的名称来创建.而创建Object类型的实例并为其添加属性和(或)方 ...

  2. 【转】JDBC学习笔记(7)——事务的隔离级别&批量处理

    转自:http://www.cnblogs.com/ysw-go/ 数据库事务的隔离级别 对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发 ...

  3. Linux--管道pipe

    管道是一种最基本的IPC机制,由pipe函数创建:#include <unistd.h>
int pipe(int filedes[2]); 调用pipe函数时在内核中开辟一块缓冲区(称为 ...

  4. 移动端H5开发 (滑动事件)

    最近一直在做手机App H5的开发,在开发过程中,经常会遇到很多滑动事件,写个demo,分享自己的一些写法.(如写的不好,轻喷!) 直接贴代码 html css代码 <!DOCTYPE html ...

  5. ORA-01034: ORACLE not available ORA-27101: shared memory realm does not exist

    Oracle 设置默认数据库 如果我们的服务器上或者电脑上安装了多个数据库,当我们使用sqlplus时如果为指定数据库时登录到的是哪一个数据库呢?今天遇到了一个老问题: ORA-01034: ORAC ...

  6. 568. Maximum Vacation Days

    Problem statement:  LeetCode wants to give one of its best employees the option to travel among N ci ...

  7. fgets()函数以及fputs()函数

    fgets() fgets() 该函数是一个文件操作相关的函数 暂时使用这个函数可以从键盘接收一个字符串,保存到字符数组中 原来接收字符串保存到数组中的方法: char str[50]; 1) sca ...

  8. linux下vim编辑器使用

    VIM - Vi IMproved: vim是vi编辑器的升级版,是linux下标准的编辑器,具有程序编写能力,可以根据字体颜色辨别语法的正确性,方便程序的设计. 使用: # vim [OPTION] ...

  9. linux下MongoDB客户端shell基本操作

    MongoDB 是一款NoSql数据库,没有固定的模式,即同一个集合中的不同文档结构可以不同,如:第一条记录{name:”xiaoming”},第二条记录:{name:”xiaoli”,age:15} ...

  10. js算法集合(一) 水仙花数 及拓展(自幂数的判断)

    js算法集合(一) ★ 最近有些朋友跟我说对js中的一些算法感到很迷惑,知道这个算法到底是怎么回事,但是就是不会用代码把它写出来,这里我跟大家分享一下做水仙花数的算法的思路,并对其扩展到自幂数的算法, ...