听老师讲课,越来越感觉自己学的太少了啊,,,还有太多东西没学,最近效率太低了。
划分树和归并树相似,不过归并树是从有序到无序()
而划分树则是从无序到有序
(红色部分代表进入左子树的数值)
划分树中每个节点记录两个信息,
struct node
{
int num[MAXN],cnt[MAXN];
//num,该层储存的数组
//cnt[i]表示此层i节点向左有多少数值进入左子树
} tree[20];//tree[deep]代表深度为deep的那一层 建树
确定一层中某个数值进入左子树还是右子树,依靠一个原数组排序后的sort【mid】的值确定,
同时为了
有空重新画吧。。不过虽然丑意思还是在的。。)
为了使划分树的每一节点的元素等于区间长度
我们对于相等的数,就不能全部放到左子树
只能放一部分给左子树
我们对于相等的数,就不能全部放到左子树
只能放一部分给左子树
void build(int t,int L,int R)
{
if (L==R)
return;
int mid=(L+R)>>1,key=sorted[mid],scnt=mid-L+1,i;
for(i=L; i<=R; ++i)
if(tree[t].num[i]<key)
--scnt;//计算有多少等于sort[mid]的元素要进入左子树
int l=L-1,r=mid,cnt=0;
for (i=L; i<=R; ++i)
{
int num=tree[t].num[i];
if (num < key || (num == key && scnt))
{
//把小于等于key的数放入左树,否则放入右树
if (num == key)
--scnt;
++cnt;
tree[t+1].num[++l]=num;
}
else
tree[t+1].num[++r]=num;
tree[t].cnt[i]=cnt;
//记录当前放入左树的数的个数
}
build(t+1,L,mid);
build(t+1,mid+1,R);
}
查询
摘自:https://blog.csdn.net/Akatsuki__Itachi/article/details/80030929
对我又懒了)
附求区间第k大板子
//#include <bits/stdc++.h>
#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<stack>
#include<ctime>
#include<cstdio>
#include<vector>
#include<string>
#include<sstream>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=1e5+10;
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define mod 1000000009
#define endll printf("\n")
#define s1(a) scanf("%d",&a)
#define s2(a,b) scanf("%d %d",&a,&b)
#define mem(a,b) memset(a,b,sizeof(a))
#define s3(a,b,c) scanf("%d %d %d",&a,&b,&c)
struct node
{
int num[MAXN],cnt[MAXN];
//num,该层储存的数组
//cnt[i]表示此层i节点向左有多少数值进入左子树
} tree[20];//tree[deep]代表深度为deep的那一层
int sorted[MAXN],ans;
void build(int t,int L,int R)
{
if (L==R)
return;
int mid=(L+R)>>1,key=sorted[mid],scnt=mid-L+1,i;
for(i=L; i<=R; ++i)
if(tree[t].num[i]<key)
--scnt;//计算有多少等于sort[mid]的元素要进入左子树
int l=L-1,r=mid,cnt=0;
for (i=L; i<=R; ++i)
{
int num=tree[t].num[i];
if (num < key || (num == key && scnt))
{
//把小于等于key的数放入左树,否则放入右树
if (num == key)
--scnt;
++cnt;
tree[t+1].num[++l]=num;
}
else
tree[t+1].num[++r]=num;
tree[t].cnt[i]=cnt;
//记录当前放入左树的数的个数
}
build(t+1,L,mid);
build(t+1,mid+1,R);
}
void query(int t,int L,int R,int l,int r,int k)
{
if (L==R)
{
ans=tree[t].num[L];
return;
}
int mid=(L+R)>>1,left=0,sum_l=tree[t].cnt[r],new_l,new_r;
if (L != l)
{
left=tree[t].cnt[l-1];
sum_l-=left;
}
if (sum_l >= k)
{
new_l=L+left;
new_r=new_l+sum_l-1;
query(t+1,L,mid,new_l,new_r,k);
}
else
{
new_l=mid+1+l-L-left;
new_r=new_l+r-l-sum_l;
query(t+1,mid+1,R,new_l,new_r,k-sum_l);
}
}
int main()
{
int n,m,i,l,r,k;
while (~scanf("%d%d",&n,&m))
{
for (i=1; i<=n; ++i)
{
scanf("%d",sorted+i);
tree[0].num[i]=sorted[i];
}
sort(sorted+1,sorted+n+1);
build(0,1,n);
while (m--)
{
scanf("%d%d%d",&l,&r,&k);
query(0,1,n,l,r,k);
printf("%d\n",ans);
}
}
} 
京公网安备 11010502036488号