poj-2823
来源:互联网 发布:mysql时间转换成毫秒值 编辑:程序博客网 时间:2024/06/05 08:24
// 24976K 6125MS C++#include <cstdio>#include <cstring>using namespace std;#define K_MAX 1000010#define INF 99999999struct TreeNode { int left; int right; int max; int min;};typedef struct TreeNode TreeNode;TreeNode tree[K_MAX<<2];int K;int replacePos;int ArrayLength;void buildTree(int pos, int begin, int end) { tree[pos].left = begin; tree[pos].right = end; tree[pos].max = -INF; tree[pos].min = INF; // tree[pos].initialzed = 0; if (begin == end) { return; } else { int mid = (begin + end)>>1; buildTree(pos<<1, begin, mid); buildTree(pos<<1|1, mid+1, end); }}void updateTreeNode(int pos) { if (pos <= 0) { // reach top. return; } else { int leftPos = pos<<1; int rightPos = pos<<1|1; TreeNode & leftNode = tree[leftPos]; TreeNode & rightNode = tree[rightPos]; tree[pos].max = leftNode.max > rightNode.max ? leftNode.max : rightNode.max; tree[pos].min = leftNode.min < rightNode.min ? leftNode.min : rightNode.min; updateTreeNode(pos>>1); }}void insertTree(int pos, int replaceId, int newVal) { int left = tree[pos].left; int right = tree[pos].right; if (left == right && left == replaceId) { // only one number in this range tree[pos].max = newVal; tree[pos].min = newVal; // tree[pos].initialzed = 1; updateTreeNode(pos>>1);// update parent node } else { int mid = (left + right)>>1; if (replaceId <= mid) { // in left part insertTree(pos<<1, replaceId, newVal); } else { // in right part insertTree(pos<<1|1, replaceId, newVal); } }}int array[K_MAX];int arrayKMin[K_MAX];int arrayKMax[K_MAX];int arrayKLength;int main() { while(scanf("%d %d", &ArrayLength, &K) != EOF) { buildTree(1, 1, K); replacePos = 1; arrayKLength = 0; for (int i = 1; i <= ArrayLength; i++) { scanf("%d", array + i -1); } for (int i = 1; i <= ArrayLength; i++) { int val = array[i - 1]; // scanf("%d", &val); if (i <= K) { // not fully-filled yet. insertTree(1, i, val); if (i == K) { arrayKMin[arrayKLength] = tree[1].min; arrayKMax[arrayKLength] = tree[1].max; arrayKLength++; } } else { // begin replace insertTree(1, replacePos, val); replacePos++; if (replacePos >= K +1) { replacePos = 1; } arrayKMin[arrayKLength] = tree[1].min; arrayKMax[arrayKLength] = tree[1].max; arrayKLength++; // printf("A %d %d\n", tree[1].min, tree[1].max); } } for (int i = 1; i <= arrayKLength; i++) { printf("%d ", arrayKMin[i - 1]); } printf("\n"); for (int i = 1; i <= arrayKLength; i++) { printf("%d ", arrayKMax[i - 1]); } printf("\n"); }}
G++ TLE... C++倒是过了。
貌似这道题最优解法是单调队列,不过用线段树也可以解出来,就用一把,
从应用角度看,是线段树的基础应用,并且可以体现线段树的优势:动态变化的数组,也可以很快得到答案。
不过这里面有一个小问题:那就是如何表示 window每次滑动带来的影响,因为每次滑动一个单位,就去掉一个数,引入一个新数,
线段树中,如果纯模拟线性数组的这种移动行为,就要对线段树的每个区间进行一次更新,绝对TLE,也体现不出线段树的优势,
一个办法就是维护一个变量R,保存这样一个值: 下一次滑动,要从数组中去掉的那个数的位置,然后将这个位置的数替换为新数即可,然后R++(下一个数就是下一次移动一应该去掉的数), 如果R>K, 那R 重置为 1
例子:
1 2 3 4 5 6 7
设窗口的长度为3, 那么初始就是 1 2 3, R = 1
移动以后: 4 2 3, R =2
再次移动: 4 5 3, R = 3
再次移动: 4 5 6, R = 1(重置为1)
这个过程就比较清晰解释了, 因为只需要求最大,最小,因为,对于窗口内部数的顺序是完全不care的,
所以每次滑动,只要能 去掉该去的数,加入新的数即可,
用这种办法,不需要更新线段树的每个区间,之需要更新R指定的单位区间即可,然后向上更新父区间的最大最小值即可,
一个值得记住的trick
0 0
- poj 2823
- POJ 2823
- poj 2823
- POJ 2823
- poj 2823
- POj 2823
- POJ 2823
- POJ 2823
- poj-2823
- POJ 2823
- poj 2823
- poj 2823
- poj 2823
- 【POJ】2823
- POJ 2823 Sliding Window
- poj 2823 Sliding Window
- Poj 2823 (单调队列)
- poj 2823【单调队列】
- maven之snapshot
- UVA - 10249 The Grand Dinner
- 考虑十进制数
- 轻松自在,Word全角半角来回转
- 关于 Eclipse 创建 Dynamic Web Project (动态的 WEB 项目) 为什么会出现没有web.xml配置文件的问题
- poj-2823
- 《算法导论》练习题--插入排序
- Toxophily(纯粹的物理公式 + 一元二次方程)
- 设计模式中类的关系
- UVA - 107 The Cat in the Hat
- js中通过构造函数创建对象
- Nginx(二)通过SVN获得Nginx源码
- POJ 2253 Frogger
- IO流缓冲区对象的使用和理解。