hdu 4417 划分树 求一个区间内小于n的数

来源:互联网 发布:h3c 怎么修改端口23 编辑:程序博客网 时间:2024/06/05 19:58

昨天才开始看划分树,本来国庆都应该看的,但是自制力太差了,好友推荐了几部电影,没有抵得住诱惑!

划分树:基于线段树的数据结构,利用归并排序用O(lgn)的方法对数据进行排序更新。

题目大意:给定一个数组,求在一个区间内小于等于n的

/////////////////////////////////////////////////////////////////////////// File Name: 4417.cpp// Author: wang// mail: // Created Time: 2013/10/10 22:47:48/////////////////////////////////////////////////////////////////////////#include <cstdio>#include <cstdlib>#include <climits>#include <cstring>#include <cmath>#include <algorithm>#include<iostream>#include<queue>#include <map>using namespace std;typedef long long ll;#define INF (INT_MAX/10)#define SQR(x) ((x)*(x))#define rep(i, n) for (int i=0; i<(n); ++i)#define repf(i, a, b) for (int i=(a); i<=(b); ++i)#define repd(i, a, b) for (int i=(a); i>=(b); --i)#define clr(ar,val) memset(ar, val, sizeof(ar))#define N 100005#define M 20int aleft[M][N];int tree[M][N];int n,m;int a[N];void bulidtree(int l,int r,int dep){if(l==r){tree[dep+1][l]=tree[dep][l];return ;}int mid=(l+r)/2;int x=a[mid];int lsame=l-1;repf(i,l,r)if(tree[dep][i]<x)lsame++;int newl=l,newr=mid+1;repf(i,l,r){if(tree[dep][i]<x)tree[dep+1][newl++]=tree[dep][i];else if(tree[dep][i]==x && lsame<mid)tree[dep+1][newl++]=tree[dep][i],lsame++;else tree[dep+1][newr++]=tree[dep][i];aleft[dep][i]=aleft[dep][l-1]+newl-l;}bulidtree(l,mid,dep+1);bulidtree(mid+1,r,dep+1);}int query(int L,int R,int l,int r,int dep,int h){if(l==r){if(tree[dep][l]<=h) return 1;else return 0;}if(l>r) return 0;int mid=(L+R)/2;int s=aleft[dep][r]-aleft[dep][l-1];int ss=aleft[dep][l-1]-aleft[dep][L-1];int e=r-l+1-s;int ee=l-L-ss;int x=a[mid];if(x<=h){int newl=mid+ee+1;int newr=mid+ee+e;return s+query(mid+1,R,newl,newr,dep+1,h);}else{int newl=L+ss;int newr=newl+aleft[dep][r]-aleft[dep][l-1]-1;return query(L,mid,newl,newr,dep+1,h);}}int main(){int test;scanf("%d",&test);int l,r,h;repf(ror,1,test){scanf("%d%d",&n,&m);repf(i,1,n)scanf("%d",&tree[0][i]),a[i]=tree[0][i];sort(a+1,a+n+1);bulidtree(1,n,0);/*repf(i,0,5){repf(j,1,10)cout<<tree[i][j]<<" ";cout<<endl;} cout<<endl;repf(i,0,5){repf(j,1,10) cout<<aleft[i][j]<<" ";cout<<endl;}*/printf("Case %d:\n",ror);repf(i,1,m){scanf("%d%d%d",&l,&r,&h);            printf("%d\n",query(1,n,l+1,r+1,0,h));}}return 0;}

数的个数。

划分树的裸题,第一次写,调了好久,但是1A了,好高兴啊!