这次是彻底把划分树搞明确了,与此同一时候发现了模版的重要性。敲代码一个字符都不能错啊~~~

划分树具体解释:点击打开链接

题意:求一组数列中随意区间不大于h的个数。

这个题的做法是用二分查询  求给定区间内的中值再与K进行比較。

重点介绍划分树:

数据结构:

t[20][maxn] // 树结构,划分树存储

sum[20][maxn] // 记录该行[l,i] 中i到l有多少个存在左子树中

as[maxn]  //原始数组排序后结果

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <bitset>
#include <iostream>
#include <algorithm>
#define inf 0x3fffffff
#define mid ((l+r)>>1)
const int maxn=100000+100;
typedef unsigned __int64 ull;
using namespace std;
int N,M; int t[30][maxn]; // 树结构,划分树存储
int sum[30][maxn]; // 记录该行[l,i] 中i到l有多少个存在左子树中
int as[maxn];//排序后数组 //建树是根据上一层建立下一层,所以t[p+1][ls++]=t[p][i]; l==r推断的条件放在循环后是为了让每一个元素都到最底层
void build(int p,int l,int r)
{
int ls=l,rs=mid+1;
int lm=0,i;
for(i=rs-1;i>=l;i--)// ls rs 左右子树開始的位置 lm 放入左子树的中值数目(避免中值过多树不平衡)
if(as[i]==as[mid]) lm++;
else break;
for(i=l;i<=r;i++)
{
if(i==l) sum[p][i]=0;//sum的计算若为初始则为0。注意这里的每行sum有多个分开的树
else sum[p][i]=sum[p][i-1];
if(t[p][i]==as[mid])
if(lm) //将部分中值的数放入左边
lm--,sum[p][i]++,t[p+1][ls++]=t[p][i];
else t[p+1][rs++]=t[p][i];
else if(t[p][i]<as[mid]) sum[p][i]++,t[p+1][ls++]=t[p][i];//小于中值放入左边
else t[p+1][rs++]=t[p][i];//大于放入右边。sum与其无关
}
if(l==r) return;
build(p+1,l,mid);
build(p+1,mid+1,r); }
/*
在p层,[l,r]范围内查询[ql,qr]中第K大数
l+s 跳过查询区间前放入左子树个数,l+sum[p][qr]-1 [l,qr]放入左子树的个数
ql-l-s 查询区间前放入右子树的个数,qr-l-sum[p][qr] [l,qr]放入右子树的个数
*/
int query(int p,int l,int r,int ql,int qr,int k)
{
if(l==r) return t[p][l];
int s,ss;//s是ql左边有多少放入下层左子树,ss是[ql,qr]中有多少放入下层左子树
if(ql==l)
s=0,ss=sum[p][qr];
else
s=sum[p][ql-1],ss=sum[p][qr]-s;
if(k<=ss)
return query(p+1,l,mid,l+s,l+sum[p][qr]-1,k);
else
return query(p+1,mid+1,r,mid+1+ ql-l-s,mid+1 +qr-l-sum[p][qr],k-ss);
} int main()
{
int T;
int n,m,cas=1;
int i,l,r,k;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&M);
for(i=0;i<N;i++)
scanf("%d",as+i),t[0][i]=as[i];
sort(as,as+N);
build(0,0,N-1);
printf("Case %d:\n",cas++);
for(i=0;i<M;i++)
{
scanf("%d%d%d",&l,&r,&k);
int mi=1,ma=r-l+1,Mid,ans=r-l+2;
while(mi<=ma)
{
Mid=(mi+ma)>>1;
int tmp=query(0,0,N-1,l,r,Mid);
if(tmp>k)
{
ans=Mid;
ma=Mid-1;
}
else
mi=Mid+1;
}
printf("%d\n",ans-1);
} }
return 0;
}

归并树:

就是在归并过程中保存结果。由于归并排序与线段树建树类似都是自底向上,所以能够保存。(这个比划分树好理解多了)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<stack>
#include<algorithm>
#include<string>
#define LL long long
#define LD long double
#define eps 1e-7
#define inf 1<<30
#define MOD 1000000007
#define N 100005
using namespace std;
struct MergeTree{
int left,right,mid;
}tree[N*4];
int num[N],mer[20][N];
int n,q;
void create(int step,int l,int r,int deep){
tree[step].left=l;
tree[step].right=r;
tree[step].mid=(l+r)>>1;
if(l==r){
mer[deep][l]=num[l];
return;
}
create(step<<1,l,(l+r)/2,deep+1);
create((step<<1)|1,(l+r)/2+1,r,deep+1);
int i=l,j=(l+r)/2+1,p=l;
//归并排序。在建树的时候保存
while(i<=(l+r)/2&&j<=r){
if(mer[deep+1][i]>mer[deep+1][j])
mer[deep][p++]=mer[deep+1][j++];
else
mer[deep][p++]=mer[deep+1][i++];
}
while(i<=(l+r)/2)
mer[deep][p++]=mer[deep+1][i++];
while(j<=r)
mer[deep][p++]=mer[deep+1][j++];
}
int query(int step,int l,int r,int deep,int key){
if(tree[step].right<l||tree[step].left>r)
return 0;
if(tree[step].left>=l&&tree[step].right<=r)
//找到key在排序后的数组中的位置
return lower_bound(&mer[deep][tree[step].left],&mer[deep][tree[step].right]+1,key)-&mer[deep][tree[step].left];
return query(2*step,l,r,deep+1,key)+query(2*step+1,l,r,deep+1,key);
}
int slove(int l,int r,int k){
int high=n,low=1,mid;
//二分答案
while(low<high){
mid=(low+high+1)>>1;
int cnt=query(1,l,r,1,mer[1][mid]);
if(cnt<=k)
low=mid;
else
high=mid-1;
}
return mer[1][low];
}
int main(){
while(scanf("%d%d",&n,&q)!=EOF){
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
create(1,1,n,1);
while(q--){
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",slove(l,r,k-1));
}
}
return 0;
}

hdu 4417,poj 2104 划分树(模版)归并树(模版)的更多相关文章

  1. poj 2104 K-th Number(主席树,详细有用)

    poj 2104 K-th Number(主席树) 主席树就是持久化的线段树,添加的时候,每更新了一个节点的线段树都被保存下来了. 查询区间[L,R]操作的时候,只需要用第R棵树减去第L-1棵树就是区 ...

  2. K-th Number 线段树(归并树)+二分查找

    K-th Number 题意:给定一个包含n个不同数的数列a1, a2, ..., an 和m个三元组表示的查询.对于每个查询(i, j, k), 输出ai, ai+1, ... ,aj的升序排列中第 ...

  3. K-th Number POJ - 2104 划分树

    K-th Number You are working for Macrohard company in data structures department. After failing your ...

  4. HDU 2665 && POJ 2104(主席树)

    http://poj.org/problem?id=2104 对权值进行建树(这个时候树的叶子是数组b的有序数列),然后二分查找原数列中每个数在有序数列中的位置(即第几小),对每一个前缀[1,i]建一 ...

  5. HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)

    Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...

  6. HDU 3966 & POJ 3237 & HYSBZ 2243 & HRBUST 2064 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  7. hdu 1540/POJ 2892 Tunnel Warfare 【线段树区间合并】

    Tunnel Warfare                                                             Time Limit: 4000/2000 MS ...

  8. POJ 2104 K-th Number(主席树——附讲解)

    Description You are working for Macrohard company in data structures department. After failing your ...

  9. HDU 4417 - Super Mario ( 划分树+二分 / 树状数组+离线处理+离散化)

    题意:给一个数组,每次询问输出在区间[L,R]之间小于H的数字的个数. 此题可以使用划分树在线解决. 划分树可以快速查询区间第K小个数字.逆向思考,判断小于H的最大的一个数字是区间第几小数,即是答案. ...

随机推荐

  1. zabbix报警邮件qq邮箱收不到的问题

    出现这样问题的根本原因是因为zabbix对中文支持不太友好,乱码导致了邮件无法正常接收. 一.解决zabbix邮件内容为附件 1.安装发送邮件的mailx 以及windows文件转unix文件的命令 ...

  2. HDU 6237.A Simple Stone Game-欧拉函数找素因子 (2017中国大学生程序设计竞赛-哈尔滨站-重现赛)

    A Simple Stone Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Ot ...

  3. 后门构建工具Backdoor Factory

    后门构建工具Backdoor Factory   在渗透测试中,后门程序帮助渗透测试人员在目标机器上执行各种预期的操作.例如,它可以建立从目标主机到攻击机的网络连接,方便渗透测试人员控制目标主机.Ka ...

  4. [BZOJ 1806] Miners 矿工配餐

    Link: BZOJ 1806 传送门 Solution: 为了使状态包含每个节点前所有必须的信息: 设$dp[i][a1][a2][b1][b2]$为配送到第$i$个,一厂前两个为$a1,a2$,二 ...

  5. POJ 2109 Inner Vertices(扫描线+树状数组)

    [题目链接] http://poj.org/problem?id=3109 [题目大意] 在一个棋盘上放满白子,现在把一些白子变成黑子, 如果一个白子上下左右都有黑子,就会变成黑子,问最终黑子个数 [ ...

  6. jQuery滑动方法

    jQuery 滑动方法 通过 jQuery,您可以在元素上创建滑动效果. jQuery 拥有以下滑动方法: slideDown() slideUp() slideToggle() jQuery sli ...

  7. linux-系统资源查看-动态

    1.top 2.sar http://blog.csdn.net/hguisu/article/details/7493661  很重要 http://blog.itpub.net/24435147/ ...

  8. 自动化安装SQLSERVER和SQLSERVER补丁 转

    2014-01-23 18:31  您还在用下一步下一步的方式安装SQLSERVER和SQLSERVER补丁吗? 介绍 假如你有50台服务器需要安装SQLSERVER,如果你用下一步下一步的方式,用远 ...

  9. Eclipse下的java工程目录

    对新手来讲,一个Java工程内部的多个文件夹经常会让大家困惑.更可恶的是莫名其妙的路径问题,在Eclipse编写Java程序中,出现频率最高的错误很可能就是路径问题. 这些问题原因其实都是一个,就是关 ...

  10. python urllib2使用细节

    刚好用到,这篇文章写得不错,转过来收藏.    转载自 道可道 | Python 标准库 urllib2 的使用细节 Python 标准库中有很多实用的工具类,但是在具体使用时,标准库文档上对使用细节 ...