Online Judge 2014 K-th Number -主席树
You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment.
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?"
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.InputThe first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000).
The second line contains n different integer numbers not exceeding 10 9 by their absolute values --- the array for which the answers should be given.
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).OutputFor each question output the answer to it --- the k-th number in sorted a[i...j] segment.
Sample Input
7 3 1 5 2 6 3 7 4 2 5 3 4 4 1 1 7 3
Sample Output
5 6 3
Hint
This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.
很裸的主席树模板题。不知道可不可以用O(n1.5log2n)的莫队加平衡树来做。
如果用下面这段代码去过poj的话会T掉,如果不是用new动态分配内存而是直接分配一个数组,在数组中储存所有节点可能就可以过了。
Code
1 /** 2 * OpenJudge 3 * Bailian#2104 4 * Accepted 5 * Time:2247ms 6 * Memory:65536k 7 */ 8 #include<iostream> 9 #include<fstream> 10 #include<sstream> 11 #include<cstdio> 12 #include<cstdlib> 13 #include<cstring> 14 #include<ctime> 15 #include<cctype> 16 #include<cmath> 17 #include<algorithm> 18 #include<stack> 19 #include<queue> 20 #include<set> 21 #include<map> 22 #include<vector> 23 using namespace std; 24 typedef bool boolean; 25 #define smin(a, b) (a) = min((a), (b)) 26 #define smax(a, b) (a) = max((a), (b)) 27 template<typename T> 28 inline void readInteger(T& u){ 29 char x; 30 int aFlag = 1; 31 while(!isdigit((x = getchar())) && x != '-' && x != -1); 32 if(x == -1){ 33 ungetc(x, stdin); 34 return; 35 } 36 if(x == '-'){ 37 x = getchar(); 38 aFlag = -1; 39 } 40 for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0'); 41 ungetc(x, stdin); 42 u *= aFlag; 43 } 44 45 typedef class SegTreeNode{ 46 public: 47 int s; //size 48 SegTreeNode *left, *right; 49 SegTreeNode():left(NULL), right(NULL), s(0){ } 50 void pushUp(){ 51 this->s += this->left->s + this->right->s; 52 } 53 }SegTreeNode; 54 55 typedef class SegTree{ 56 public: 57 SegTreeNode* root; 58 SegTree():root(NULL){ } 59 SegTree(int size, int val){ 60 build(root, 1, size, val); 61 } 62 SegTree(SegTreeNode* root):root(root){ } 63 64 void build(SegTreeNode*& node, int from, int end, int val){ 65 node = new SegTreeNode(); 66 if(from == end){ 67 node->s = (val == from) ? (1) : (0); 68 return; 69 } 70 int mid = (from + end) >> 1; 71 build(node->left, from, mid, val); 72 build(node->right, mid + 1, end, val); 73 node->pushUp(); 74 } 75 }SegTree; 76 77 typedef class Pair{ 78 public: 79 int data; 80 int index; 81 Pair(const int data = 0, const int index = 0):data(data), index(index){ } 82 boolean operator < (Pair another) const { 83 return data < another.data; 84 } 85 }Pair; 86 87 typedef class ChairTree{ //主席树 88 public: 89 SegTree* st; 90 int* discrete; 91 map<int, int> to; 92 int len; 93 ChairTree():st(NULL), discrete(NULL){ } 94 ChairTree(int* lis, int len):len(len){ 95 discrete = new int[(const int)(len + 1)]; 96 memcpy(discrete, lis, sizeof(int) * (len + 1)); 97 sort(discrete + 1, discrete + len + 1); 98 for(int i = 1; i <= len; i++) 99 to[discrete[i]] = i; 100 st = new SegTree[(const int)(len + 1)]; 101 st[0] = SegTree(len, 0); 102 for(int i = 1; i <= len; i++){ 103 st[i] = SegTree(); 104 appendSegTree(st[i].root, st[i - 1].root, 1, len, to[lis[i]]); 105 } 106 } 107 108 void appendSegTree(SegTreeNode*& node, SegTreeNode*& before, int from, int end, int val){ 109 node = new SegTreeNode(); 110 if(from == end){ 111 node->s = 1; 112 return; 113 } 114 int mid = (from + end) >> 1; 115 if(val <= mid){ 116 node->right = before->right; 117 appendSegTree(node->left, before->left, from, mid, val); 118 }else{ 119 node->left = before->left; 120 appendSegTree(node->right, before->right, mid + 1, end, val); 121 } 122 node->pushUp(); 123 } 124 125 int query(int l, int r, SegTreeNode*& left, SegTreeNode*& right, int k){ 126 if(l == r){ 127 return l; 128 } 129 int ls = left->left->s - right->left->s; 130 int mid = (l + r) >> 1; 131 if(ls >= k) return query(l, mid, left->left, right->left, k); 132 return query(mid + 1, r, left->right, right->right, k - ls); 133 } 134 135 int query(int from, int end, int k){ 136 return discrete[query(1, len, st[end].root, st[from - 1].root, k)]; 137 } 138 }ChairTree; 139 140 int n, m; 141 ChairTree ct; 142 int *lis; 143 144 inline void init(){ 145 readInteger(n); 146 readInteger(m); 147 lis = new int[(const int)(n + 1)]; 148 for(int i = 1; i <= n; i++){ 149 readInteger(lis[i]); 150 } 151 ct = ChairTree(lis, n); 152 } 153 154 inline void solve(){ 155 int l, r, k; 156 while(m--){ 157 readInteger(l); 158 readInteger(r); 159 readInteger(k); 160 int res = ct.query(l, r, k); 161 printf("%d\n", res); 162 } 163 } 164 165 int main(){ 166 init(); 167 solve(); 168 return 0; 169 }