poj2823 线段树模板题 点修改(也可以用单调队列)

这道题吧 没计算时间 因为给了那么多 一算还可以

就直接写了线段树,刘汝佳那本模板

然后!poj的g++比C++慢大约500ms。。。。。。。g++tle,C++就过了

Sliding Window

Time Limit: 12000MS   Memory Limit: 65536K
Total Submissions: 67576   Accepted: 19163
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

Source

POJ Monthly--2006.04.28, Ikki

上代码 通俗易懂哦~~~~~~看我的就行了

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

int Max[5000100];
int Min[5000100];
int pinf = 2000000000;
int ninf = -2000000000;
int n,k;

void build(int l,int r,int cur){
    if(l == r){
        scanf("%d",&Max[cur]);
        Min[cur] = Max[cur];
        return;
    }
    int mid = (l + r)/2;
    build(l,mid,cur*2);
    build(mid + 1,r,cur*2 + 1);
    Min[cur] = min(Min[cur*2],Min[cur*2 + 1]);
    Max[cur] = max(Max[cur*2],Max[cur*2 + 1]);
    return;
}

int ql,qr;
int queryMax(int l,int r,int cur){
    if(ql <= l&&r <= qr){
        return Max[cur];
    }
    int mid = (l + r)/2;
    int ans = ninf;
    if(ql <= mid){
        ans = max(ans,queryMax(l,mid,cur*2));
    }
    if(qr > mid){
        ans = max(ans,queryMax(mid + 1,r,cur*2 +1));
    }
    return ans;
}
int queryMin(int l,int r,int cur){
    if(ql <= l && r <= qr){
        return Min[cur];
    }
    int mid = (l + r)/2;
    int ans = pinf;
    if(ql <= mid){
        ans = min(ans,queryMin(l,mid,cur*2));
    }
    if(qr > mid){
        ans = min(ans,queryMin(mid + 1,r,cur*2 + 1));
    }
    return ans;
}

int main(){
    while(scanf("%d%d",&n,&k) != EOF){
        build(1,n,1);
        ql = 1;qr = k;
        printf("%d",queryMin(1,n,1));
        ql++;qr++;
        while(qr <= n){
            printf(" %d",queryMin(1,n,1));
            ql++;qr++;
        }
        printf("\n");

        ql = 1;qr = k;
        printf("%d",queryMax(1,n,1));
        ql++;qr++;
        while(qr <= n){
            printf(" %d",queryMax(1,n,1));
            ql++;qr++;
        }
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/xuyanqd/p/9073920.html

时间: 2024-10-07 07:04:29

poj2823 线段树模板题 点修改(也可以用单调队列)的相关文章

[POJ2104] 区间第k大数 [区间第k大数,可持久化线段树模板题]

可持久化线段树模板题. #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <vector> using namespace std; int n,q,tot,a[110000]; in

LA 2191电位计(线段树模板题)

线段树模板题,没啥好说的.....注意输出是case之间空一行就行.........之前一直没注意,一直wa 代码如下: #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #includ

1270. 数列区间最大值(climits用法+线段树模板题)

题目链接: https://www.acwing.com/problem/content/1272/ 题解: 线段树模板题,单点求和.区间查询都可 AC代码: #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <climits> using namespace std; const int N = 1e5+10; int a

P1243~P1247 线段树模板题总结

前言 这几天刚刚刷了5道线段树(水)题,现在来总结一下. 首先是犯的不少错误: 1.建树.更新函数没有return.这是最气的,每次最后程序错误查了半天也没查出来,最后发现是没有return.递归边界要return,递归边界要return,递归边界要return,重要的事情说三遍. 2.判断查找区间于线段的变量写反.听说这个是常犯错误. 然后说一下学线段树的收获.线段树的代码量的确多,很能练自己的思维,而且学的过程中简单的理解了一下#define的用处.线段树用来解决区间查询,区间修改都很方便,

HDU 1166 线段树模板题

坐了3天的火车,终于到外婆家了(┬_┬).这次北京之旅颇有感触,虽然学到的东西不是很多(主要是自己的原因,没有认真学,并不是老师讲的不好),不过出去见见世面也是好的.最后一场比赛印象颇深,被虐的有点惨....记得当时有道题感觉自己能过,想用数组模拟链表水过,可是无论怎么优化一直超时@[email protected]后面比完后听朋友说那题应该用线段树做,顿时恍然大悟,然并卵,线段树的模板早忘了.....今天做道线段树的模板题先复习一下,过会再想想那道题. 敌兵布阵 Time Limit: 200

权值线段树模板题

array Time Limit: 1500ms Memory Limit: 256M Description You are given an array . Initially, each element of the array is unique.Moreover, there are  instructions. Each instruction is in one of the following two formats: 1. ,indicating to change the v

HDU1754 线段树模板题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 题目分析:对于给出的一个很长的区间,对其进行单点更新值和区间求最大值的操作,由于查询的区间很大,且查询次数多,这里用线段树求解将是十分合适的 注意点:1.对于存放线段树的数组大小需要开大一些 2.对于c语言的字符输入%c之前需要加一个空格保证输入准确 1 #include<iostream> 2 #include<string.h> 3 using namespace std;

[bzoj1568]李超线段树模板题(标志永久化)

题意:要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第i条被插入的线段的标号为i. 2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. 解题关键:注意标志的作用 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostrea

又长又臭又慢的线段树 模板题hdu1698 Just a Hook

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 30901    Accepted Submission(s): 15221Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing f