poj 2823 Sliding Window 线段树

太过爱你忘了你带给我的痛 2022-06-08 08:13 246阅读 0赞

Sliding Window
Time Limit: 12000MS
Memory Limit: 65536K
Total Submissions: 50906
Accepted: 14640
Case Time Limit: 5000MS
Description
An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example:
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Window position Minimum value Maximum value
[1 3 -1] -3 5 3 6 7 -1 3
1 [3 -1 -3] 5 3 6 7 -3 3
1 3 [-1 -3 5] 3 6 7 -3 5
1 3 -1 [-3 5 3] 6 7 -3 5
1 3 -1 -3 [5 3 6] 7 3 6
1 3 -1 -3 5 [3 6 7] 3 7
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line.
Output
There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values.
Sample Input
8 3
1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3
3 3 5 5 6 7
题目大意:第一行输入两个数n,k,第二行输入n个数。现在有一个长度为k的窗口,从第一个数开始滑动(每次滑动1个单位),每次只有窗口范围中的数字可见。输出两行,第一行是每次窗口中的最小数,第二行是每次窗口中的最大数。
AC代码:

  1. //用g++一直超时,要用c++,好坑
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. using namespace std;
  6. #define maxn 1000000
  7. int num[maxn];
  8. struct node
  9. {
  10. int minvalue, maxvalue; //此节点的值
  11. int left,right; //此节点所维护区间的左右端点
  12. }tree[maxn*4];
  13. struct Node
  14. {
  15. int min, max;
  16. }ans[maxn];
  17. void build(int root,int left,int right)
  18. {
  19. tree[root].left = left;
  20. tree[root].right = right;
  21. if(left == right) //区间的左右端点相同,也就是到了叶子节点
  22. {
  23. tree[root].maxvalue = tree[root].minvalue = num[left];
  24. return ;
  25. }
  26. int mid = (left+right) / 2;
  27. build(root*2, left, mid); //继续构建左子树
  28. build(root*2+1, mid+1, right); //继续构建右子树
  29. tree[root].maxvalue = max(tree[root*2].maxvalue,tree[root*2+1].maxvalue);
  30. tree[root].minvalue = min(tree[root*2].minvalue,tree[root*2+1].minvalue);
  31. }
  32. //查询left,right区间的最值 ,这里用一个flag来标记查询的是最大值还是最小值
  33. int query(int root, int left, int right, int flag)
  34. {
  35. if(tree[root].left == left&&tree[root].right == right){
  36. if(flag == 0)
  37. return tree[root].minvalue;
  38. if(flag == 1)
  39. return tree[root].maxvalue;
  40. }
  41. if(right <= tree[2*root].right) //这个区间在根的左边
  42. return query(root*2, left, right, flag);
  43. else if(left >= tree[root*2+1].left)//这个区间在根的右边
  44. return query(root*2+1, left, right, flag);
  45. else //这个区间既在根的左边又在根的右边
  46. {
  47. int mid = (tree[root].left+tree[root].right) / 2;
  48. if(flag == 0)
  49. return min(query(root*2, left, mid, flag), query(root*2+1, mid+1, right, flag));
  50. if(flag == 1)
  51. return max(query(root*2, left, mid, flag), query(root*2+1, mid+1, right, flag));
  52. }
  53. }
  54. int main()
  55. {
  56. int n, k;
  57. while(scanf("%d %d",&n, &k) != EOF){
  58. for(int i = 1; i <= n; i++)
  59. scanf("%d", &num[i]);
  60. build(1, 1, n);
  61. for(int j = 1; j <= n-k+1; j++){
  62. int right = j + k - 1;
  63. ans[j].min = query(1, j,right ,0);
  64. ans[j].max = query(1, j,right ,1);
  65. }
  66. for(int j = 1; j <= n-k+1; j++){
  67. if(j == 1)
  68. printf("%d", ans[j].min);
  69. else
  70. printf(" %d", ans[j].min);
  71. }
  72. printf("\n");
  73. for(int j = 1; j <= n-k+1; j++){
  74. if(j == 1)
  75. printf("%d", ans[j].max);
  76. else
  77. printf(" %d", ans[j].max);
  78. }
  79. printf("\n");
  80. }
  81. return 0;
  82. }

发表评论

表情:
评论列表 (有 0 条评论,246人围观)

还没有评论,来说两句吧...

相关阅读

    相关 POJ 2528 线段+离散化

        [POJ 2528][]      关键在于插入数据的顺序------从上往下依次插入每张海报,这样后插入的海报不可能覆盖先插入的海报,因此插入一张海报时,如果发现海