Kth number
Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5615 Accepted Submission(s): 1821
Problem Description
Give you a sequence and ask you the kth big number of a inteval.
Input
The first line is the number of the test cases.
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere.
The second line contains n integers, describe the sequence.
Each of following m lines contains three integers s, t, k.
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere.
The second line contains n integers, describe the sequence.
Each of following m lines contains three integers s, t, k.
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]
Output
For each test case, output m lines. Each line contains the kth big number.
Sample Input
1 10 1 1 4 2 3 5 6 7 8 9 0 1 3 2
Sample Output
2这道题的这坑!!明明求的是区间第K小的数,题意却给人一种求区间第K大的数感觉,要不是看了discuss,我可能会wrong一辈子!!这道题就是一道划分树的模板题,不是太难,刚学划分树,拿来练手 ,是最好不过的了!#include <cstdio> #include <algorithm> #define MAX 110000 using namespace std ; int sorted[MAX] , tree[30][MAX] ,toLeft[30][MAX]; void build(int left , int right , int deep) { if(left == right) { return ; } int mid = (left+right)>>1 ; int same = mid-left+1 ; for(int i = left ; i <= right ; ++i) { if(tree[deep][i]<sorted[mid]) --same ; } int ls = left; int rs = mid + 1 ; for(int i = left ; i <= right ; ++i) { int flag = 0 ; if(tree[deep][i] < sorted[mid] || (tree[deep][i]==sorted[mid] && same) ) { tree[deep+1][ls++]=tree[deep][i] ; if(tree[deep][i] == sorted[mid]) --same ; flag = 1; } else { tree[deep+1][rs++] = tree[deep][i] ; } toLeft[deep][i] = toLeft[deep][i-1] + flag ; } build(left,mid,deep+1); build(mid+1,right,deep+1); } //x,y是小区间 ,, L,R是大区间 int query(int x , int y , int k , int L , int R , int deep) { if(x == y) { return tree[deep][x] ; } int mid = (L+R)>>1 ; int lxl = toLeft[deep][x-1]-toLeft[deep][L-1];//L与x之间的有多少在左子树的 int lxr = x-L-lxl ; //Y: L与x之间在右子树的 int xyl = toLeft[deep][y]-toLeft[deep][x-1] ;// x与y之间有多少在左子树的 int lyr = y-L+1-(toLeft[deep][y]-toLeft[deep][L-1]) ;// L与y之间有多少右子树额 int lyl = toLeft[deep][y]-toLeft[deep][L-1] ; // L与y之间有多少左子树的 if(k<=xyl) { return query(L+lxl,L+lyl-1,k,L,mid,deep+1); } else { return query(mid+1+lxr , mid+lyr,k-xyl,mid+1,R,deep+1); } } int main() { int t ; scanf("%d",&t) ; while(t--) { int n , m ; scanf("%d%d",&n,&m); for(int i = 1 ; i <= n ; ++i) { scanf("%d",&sorted[i]); tree[0][i] = sorted[i]; } sort(sorted+1,sorted+n+1) ; build(1,n,0); int left, right , k; for(int i = 0 ; i < m ; ++i) { scanf("%d%d%d",&left,&right,&k) ; printf("%d\n",query(left,right,k,1,n,0));//把k改成这个right-left+2-k,就是求区间第K大的数了 } } return 0 ; }
这个代码以后就作为我的模板了