hdu 4417 Super Mario 离线线段树
思路:将点按值从小到大排序,询问按h从小到大排序。
在建立线段树,按h的大小更新树并得到该次查询的结果!
代码如下:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<cstring>
#define MAX 100005
#define I(x) scanf("%d",&x)
#define lson step<<1
#define rson step<<1|1
using namespace std;
int ans[MAX];
struct node
{
int x,y,h,id;
bool operator<(const node a)const{
return h<a.h;
}
}q[MAX];
struct point
{
int v,id;
bool operator<(const point a)const{
return v<a.v;
}
}p[MAX];
struct tree
{
int l,r,cnt;
}T[MAX<<];
void built(int step,int l,int r)
{
T[step].l=l;
T[step].r=r;
T[step].cnt=;
if(l==r) return ;
int m=(l+r)>>;
built(lson,l,m);
built(rson,m+,r);
}
void update(int step,int pos)
{
T[step].cnt++;
if(T[step].l==T[step].r) return;
int m=(T[step].l+T[step].r)>>;
if(pos<=m) update(lson,pos);
else update(rson,pos);
}
int query(int step,int l,int r)
{
if(T[step].l==l&&T[step].r==r) return T[step].cnt;
int m=(T[step].l+T[step].r)>>;
if(r<=m) return query(lson,l,r);
else if(l>m) return query(rson,l,r);
else return query(lson,l,m)+query(rson,m+,r);
}
int main()
{
int t,i,j,m,n,k,ca=;
I(t);
while(t--){
scanf("%d%d",&n,&m);
for(i=;i<n;i++){
I(p[i].v);
p[i].id=i+;
}
for(i=;i<m;i++){
scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].h);
q[i].id=i;
}
built(,,n);
sort(p,p+n);
sort(q,q+m);
j=;
for(i=;i<m;i++){
while(j<n&&p[j].v<=q[i].h){
update(,p[j].id);
j++;
}
ans[q[i].id]=query(,q[i].x+,q[i].y+);
}
printf("Case %d:\n",++ca);
for(i=;i<m;i++)
printf("%d\n",ans[i]);
}
return ;
}
这个是划分树做的。
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#define inf 1<<28
#define M 6000005
#define N 100005
#define maxn 300005
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define MOD 1000000007
#define lson step<<1
#define rson step<<1|1
using namespace std;
struct Node{
int left,right;
int sum;
}L[N*];
int sa[N],num[][N],cnt[][N];//sa中是排序后的,num记录每一层的排序结果,cnt[deep][i]表示第deep层,前i个数中有多少个进入左子树
void Bulid(int step,int l,int r,int deep){
L[step].left=l;
L[step].right=r;
if(l==r)
return;
int mid=(l+r)>>;
int mid_val=sa[mid],lsum=mid-l+;;
for(int i=l;i<=r;i++)
if(num[deep][i]<mid_val)
lsum--; //lsum表示左子树中还需要多少个中值
int L=l,R=mid+;
for(int i=l;i<=r;i++){
if(i==l)
cnt[deep][i]=;
else
cnt[deep][i]=cnt[deep][i-];
if(num[deep][i]<mid_val||(num[deep][i]==mid_val&&lsum>)){ //左子树
num[deep+][L++]=num[deep][i];
cnt[deep][i]++;
if(num[deep][i]==mid_val)
lsum--;
}
else
num[deep+][R++]=num[deep][i];
}
Bulid(*step,l,mid,deep+);
Bulid(*step+,mid+,r,deep+);
}
int Query(int step,int l,int r,int k,int deep){
if(l==r)
return num[deep][l];
int s1,s2; //s1为[L[step].left,l-1]中分到左子树的个数
if(L[step].left==l)
s1=;
else
s1=cnt[deep][l-];
s2=cnt[deep][r]-s1; //s2为[l,r]中分到左子树的个数
int m=(L[step].left+L[step].right)/;
if(k<=s2) //左子树的数量大于k,递归左子树
return Query(lson,L[step].left+s1,L[step].left+s1+s2-,k,deep+);
int b1=l--L[step].left+-s1; //b1为[L[step].left,l-1]中分到右子树的个数
int b2=r-l+-s2; //b2为[l,r]中分到右子树的个数
return Query(rson,m++b1,m++b1+b2-,k-s2,deep+);
}
int slove(int l,int r,int h){
int ans=,low=,high=r-l+,mid;
while(low<=high){
mid=(low+high)/;
int tmp=Query(,l,r,mid,);
if(tmp<=h){ans=mid;low=mid+;}
else high=mid-;
}
return ans;
}
int main(){
int n,q,t,cas=;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++){
scanf("%d",&sa[i]);
num[][i]=sa[i];
}
sort(sa+,sa++n);
Bulid(,,n,);
printf("Case %d:\n",++cas);
while(q--){
int l,r,h;
scanf("%d%d%d",&l,&r,&h);
l++;r++;
printf("%d\n",slove(l,r,h));
}
}
return ;
}
hdu 4417 Super Mario 离线线段树的更多相关文章
- HDU 4417 Super Mario(线段树)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 4417.Super Mario-可持久化线段树(无修改区间小于等于H的数的个数)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 4417 Super Mario (划分树)(二分)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 4417 Super Mario ( 离线树状数组 )
把数值和查询放在一起从小到大排序,纪录每个数值的位置,当遇到数值时就更新到树状数组中,遇到查询就直接查询该区间和. #include <cstdio> #include <cstri ...
- hdu 4417 Super Mario (主席树)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 题意: 给你段长为n的序列,有q个询问,每次询问区间[l.r]内有多少个数小于等于k 思路: 之前用 ...
- HDU 4417 Super Mario(主席树 区间不超过k的个数)题解
题意:问区间内不超过k的个数 思路:显然主席树,把所有的值离散化一下,然后主席树求一下小于等于k有几个就行.注意,他给你的k不一定包含在数组里,所以问题中的询问一起离散化. 代码: #include& ...
- HDU 5700 区间交 离线线段树
区间交 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5700 Description 小A有一个含有n个非负整数的数列与m个区间.每个区间可以表示为 ...
- HDU 4417 Super Mario(2012杭州网络赛 H 离线线段树)
突然想到的节约时间的方法,感觉6翻了 给你n个数字,接着m个询问.每次问你一段区间内不大于某个数字(不一定是给你的数字)的个数 直接线段树没法做,因为每次给你的数字不一样,父节点无法统计.但是离线一 ...
随机推荐
- 不用Unity库,自己实现.NET轻量级依赖注入
在面向对象的设计中,依赖注入(IoC)作为一种重要的设计模式,主要用于削减计算机程序的耦合问题,相对于Java中的Spring框架来说,微软企业库中的Unity框架是目前.NET平台中运用比较广泛的依 ...
- 【OpenCV第一篇】安装OpenCV
[OpenCV第一篇]安装OpenCV 本篇主要介绍如何下载OpenCV安装程序,如何在VS2008下安装配置OpenCV,文章最后还介绍了一个使用OpenCV的简单小例子. <OpenCV入门 ...
- CSS练习
看到一个CSS参考手册:http://css.doyoe.com/ 感谢感谢!
- WPF 使用定时器
WPF 使用定时器:<ProgressBar Height="10" HorizontalAlignment="Left" Margin="28 ...
- Zendframework application 引导过程
Applications 会期望用户提供一个配置好的ServiceManager.提供以下服务: 1.EventManager 2.ModuleManager 3.Request 4.Response ...
- ASP.NET从数据库中取出数据,有数据的复选框为选中
在KS系统中在更新菜单的时候,当查出菜单的时候要查出菜单下面已经有了哪些界面了我用了一下的方法弄的.代码如下: 界面代码: <%@ Page Language="C#" Au ...
- sql server2000中使用convert来取得datetime数据类型样式(全)
sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, 20) 结果:2007-0 ...
- AJAX请求遭遇未登录和Session失效的解决方案
使用技术:HTML + Servlet + Filter + jQuery 一般来说我们的项目都有登录过滤器,一般请求足以搞定.但是AJAX却是例外的,所以解决方法是设置响应为session失效. 一 ...
- Linux - 升级+编译kernel
For upgrading present kernel to linux-next kernel, we need to follow below steps. 1. Check present k ...
- ASP.NET Web - 开篇
ASP.NET运行库 服务器系统上需要ASP.NET运行库.如果系统上有IIS,就会在安装.NET Framework时为服务器配置ASP.NET运行库.开发过程中,不需要IIS,因为VS发布了自己的 ...