POJ 2104 解题报告

来源:互联网 发布:复杂网络包括 编辑:程序博客网 时间:2024/06/05 05:52

这道题刚开始是用quickselect做的,由于每次都要复制到一个新数组并partition,不出意料地超时了。然后看到discuss中提到划分树。用了很久才大致明白是什么意思。这里对其基本思想有很好的描述:http://blog.renren.com/blog/367737224/728617495。但是划分树的更新区间的index还是很难的。几次修改之后就和网上的代码完全一致了。比较好的链接是:http://www.cnblogs.com/yym2013/p/3714654.html和http://www.cnblogs.com/kane0526/archive/2013/04/20/3033212.html。也至少是明白代码含义了,还需要好好练练。

2104Accepted15624K1266MSG++3201B

/* ID: thestor1 LANG: C++ TASK: poj2104 */#include <iostream>#include <fstream>#include <cmath>#include <cstdio>#include <cstring>#include <limits>#include <string>#include <vector>#include <list>#include <set>#include <map>#include <queue>#include <stack>#include <algorithm>#include <cassert>using namespace std;const int MAXN = 100500;int sorted[MAXN];int nums[20][MAXN];int leftsize[20][MAXN];void build(int layer, int left, int right){// cout << "[build]layer: " << layer << ", left: " << left << ", right: " << right << endl;int mid = left + ((right - left) >> 1);int pivot = sorted[mid];int nsame = mid - left + 1;for (int i = left; i <= mid; ++i){if (sorted[i] < pivot){nsame--;}}int nextleft = left, nextright = mid + 1;for (int i = left; i <= right; ++i){if (i == left){leftsize[layer][i] = 0;}else{leftsize[layer][i] = leftsize[layer][i - 1];}if (nums[layer][i] < pivot || (nums[layer][i] == pivot && nsame >= 1)){nums[layer + 1][nextleft] = nums[layer][i];nextleft++;leftsize[layer][i]++;if (nums[layer][i] == pivot){nsame--;}}else{assert (nums[layer][i] > pivot || nsame == 0);nums[layer + 1][nextright] = nums[layer][i];nextright++;}}assert (nextleft == mid + 1 && nextright == right + 1);if (left == right){return;}build(layer + 1, left, mid);build(layer + 1, mid + 1, right);}int query(int layer, int left, int right, int queryleft, int queryright, int k){// cout << "[query]layer: " << layer << ", left: " << left << ", right: " << right << ", queryleft: " << queryleft << ", queryright: " << queryright << ", k: " << k << endl;assert (left <= queryleft && queryright <= right);if (left == right){assert (k == 1 && queryleft == queryright && queryright == left);return nums[layer][left];}int mid = left + ((right - left) >> 1);// s is the number of nums in left subtree in range [left, queryleft - 1]// ss is the number of nums in left subtree in range [queryleft, queryright]int s, ss;if (queryleft == left){s = 0;ss = leftsize[layer][queryright];}else{s = leftsize[layer][queryleft - 1];ss = leftsize[layer][queryright] - s;}if (ss >= k){// the kth number in [queryleft, queryright] is in the left subtree// cout << "[debug]go left" << endl;return query(layer + 1, left, mid, left + s, left + s + ss - 1, k);}else{// cout << "[debug]go right" << endl;return query(layer + 1, mid + 1, right, mid + 1 + queryleft - 1 - left + 1 - s, mid + 1 + queryright - left + 1 - s - ss - 1, k - ss);}}int main(){int n, m;scanf("%d%d", &n, &m);for (int i = 0; i < n; ++i){scanf("%d", &nums[0][i + 1]);sorted[i + 1] = nums[0][i + 1];}sort(sorted + 1, sorted + n + 1);build(0, 1, n);int queryleft, queryright, k;for (int i = 0; i < m; ++i){scanf("%d%d%d", &queryleft, &queryright, &k);printf("%d\n", query(0, 1, n, queryleft, queryright, k));}return 0;  }


0 0