临时文档2
臨時文檔2 #include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#define maxn 100010
#define mid ((l+r)>>1)
using namespace std;
int tree[20][maxn];//表示每層每個位置的值
int toleft[20][maxn];//20層每層maxn t用來放原序; toleft[p][i]表示第P層第i個放左節點的元素個數
int sorted[maxn];//已經排序的數
//以下為查找區間第k小劃分樹
void build(int p,int l,int r) //p:第幾層 默認0開始 ; l,r 左右區間從[1,n]開始建
{int lm=0,i,ls=l,rs=mid+1;//lm表示應被放入左子樹且與中位數相等的數有多少個,ls為左子樹的起始位置,rs為右子樹的起始位置for(i=mid;i>=l;i--) //求lm ;2 3 3 4 4 5 5 7 9得到的lm=2{if(sorted[i]==sorted[mid])lm++;elsebreak;}for(i=l;i<=r;i++){if(i==l)//這里要特殊討論toleft[p][i]=0;elsetoleft[p][i]=toleft[p][i-1];//下一個肯定是上一個+0或1if(tree[p][i]==sorted[mid])//若與中位數相等則判斷是否應該被放入左子樹{if(lm){lm--;toleft[p][i]++; //如果滿足 說明又多了一個元素放左節點了tree[p+1][ls++]=tree[p][i];//放入下一個t[]}elsetree[p+1][rs++]=tree[p][i];}else if(tree[p][i]<sorted[mid])//查找區間第K大即為>{toleft[p][i]++;tree[p+1][ls++]=tree[p][i];}elsetree[p+1][rs++]=tree[p][i];}if(l==r) return; //這個放最上邊省時build(p+1,l,mid);build(p+1,mid+1,r);
}
//查詢區間第k大的數,[L,R]是大區間,[l,r]是要查詢的小區間
int query(int p,int L,int R,int l,int r,int k)
{int s,ss;//s表示[L,l-1]放入左子樹的個數,ss表示區間[l,r]被放入左子樹的個數if(L==R)//找到所求的數return tree[p][L];if(l==L)s=0,ss=toleft[p][r];elses=toleft[p][l-1],ss=toleft[p][r]-s;if(k<=ss)//要找的數在左子樹中return query(p+1,l,mid,l+s,l+toleft[p][r]-1,k);else//要找的數在右子樹中return query(p+1,mid+1,R,mid+1-L+l-s,mid+1-L+r-toleft[p][r],k-ss);
}
int main()
{int i,n,m;scanf("%d%d",&n,&m);for(i=1;i<=n;i++){scanf("%d",& tree[0][i]);sorted[i]=tree[0][i];}sort(sorted+1,sorted+n+1);build(0,1,n);while(m--){int l,r,k;scanf("%d%d%d",&l,&r,&k);int ans=query(0,1,n,l,r,k);printf("%d\n",ans);}return 0;
}
/**input:7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3
output:
5
6
3* */
版權聲明:本文為博主原創文章,未經博主允許不得轉載。
posted on 2014-07-28 16:58 france 閱讀(...) 評論(...) 編輯 收藏轉載于:https://www.cnblogs.com/france/p/4808709.html
總結
- 上一篇: C函数数组元素初始化
- 下一篇: Flex Accordion 和 Tab