好贷网好贷款

POJ 2104 & HDU 2665 K-th Number (划分树)

发布时间:2016-12-4 5:55:27 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"POJ 2104 & HDU 2665 K-th Number (划分树)",主要涉及到POJ 2104 & HDU 2665 K-th Number (划分树)方面的内容,对于POJ 2104 & HDU 2665 K-th Number (划分树)感兴趣的同学可以参考一下。

题意不用说了,就是询问x次,指定区间的第k小的值.................... 表示太弱了.......看了许久还是不太理解划分树内涵,先把偷来的模板留着 #include <iostream> #include <algorithm> #include <cmath> #include<functional> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <vector> #include <set> #include <queue> #include <stack> #include <climits>//形如INT_MAX一类的 #define MAX 100005 #define INF 0x7FFFFFFF #define L(x) x << 1 #define R(x) x << 1 | 1 using namespace std; struct Seg_Tree { int l,r,mid; } tr[MAX*4]; int len; int sorted[MAX]; int lef[20][MAX]; int val[20][MAX]; void build(int l,int r,int step,int x) { tr[x].l = l; tr[x].r = r; tr[x].mid = (l + r) >> 1; if(tr[x].l == tr[x].r) return ; int mid = tr[x].mid; int lsame = mid - l + 1;//lsame表示和val_mid相等且分到左边的 for(int i = l ; i <= r ; i ++) { if(val[step][i] < sorted[mid]) { lsame --;//先假设左边的数(mid - l + 1)个都等于val_mid,然后把实际上小于val_mid的减去 } } int lpos = l; int rpos = mid + 1; int same = 0; for(int i = l ; i <= r ; i ++) { if(i == l) { lef[step][i] = 0;//lef[i]表示[ tr[x].l , i ]区域里有多少个数分到左边 } else { lef[step][i] = lef[step][i-1]; } if(val[step][i] < sorted[mid]) { lef[step][i] ++; val[step + 1][lpos++] = val[step][i]; } else if(val[step][i] > sorted[mid]) { val[step+1][rpos++] = val[step][i]; } else { if(same < lsame) {//有lsame的数是分到左边的 same ++; lef[step][i] ++; val[step+1][lpos++] = val[step][i]; } else { val[step+1][rpos++] = val[step][i]; } } } build(l,mid,step+1,L(x)); build(mid+1,r,step+1,R(x)); } int query(int l,int r,int k,int step,int x) { if(l == r) { return val[step][l]; } int s;//s表示[l , r]有多少个分到左边 int ss;//ss表示 [tr[x].l , l-1 ]有多少个分到左边 if(l == tr[x].l) { s = lef[step][r]; ss = 0; } else { s = lef[step][r] - lef[step][l-1]; ss = lef[step][l-1]; } if(s >= k) {//有多于k个分到左边,显然去左儿子区间找第k个 int newl = tr[x].l + ss; int newr = tr[x].l + ss + s - 1;//计算出新的映射区间 return query(newl,newr,k,step+1,L(x)); } else { int mid = tr[x].mid; int bb = l - tr[x].l - ss;//bb表示 [tr[x].l , l-1 ]有多少个分到右边 int b = r - l + 1 - s;//b表示 [l , r]有多少个分到右边 int newl = mid + bb + 1; int newr = mid + bb + b; return query(newl,newr,k-s,step+1,R(x)); } } int n,m,l,r,k; int main() { while(scanf("%d%d",&n,&m) != EOF) { for(int i=1; i<=n; i++) { scanf("%d",&val[0][i]); sorted[i] = val[0][i]; } sort(sorted + 1,sorted + 1 + n); build(1,n,0,1); for(int i=0; i<m; i++) { scanf("%d%d%d",&l,&r,&k); printf("%d\n",query(l,r,k,0,1)); } } return 0; }

上一篇:JSP Tag实现定义 java文件
下一篇:android学习笔记之Fragment(三)

相关文章

相关评论