POJ 2823 Sliding Window (线段树/单调队列)
题目不说了,可以用线段树或者单调队列,下面附上代码。
线段树:
#include <iostream>
#include <stdio.h>
#include <algorithm>
/*
AC
线段树每个节点存储对应区间的最大值、最小值,然后直接查询即可。6594MS。
*/
using namespace std;
const int maxn=;
const int INF=0x3f3f3f3f;
int minans[maxn],maxans[maxn];
int small,bigger;
int n,k;
struct Node{
int maxv,minv;
}tree[maxn<<]; void pushUp(int rt){
tree[rt].maxv=max(tree[rt<<].maxv,tree[rt<<|].maxv);
tree[rt].minv=min(tree[rt<<].minv,tree[rt<<|].minv);
} void build(int rt,int L,int R){
if(L==R){
scanf("%d",&tree[rt].minv);
tree[rt].maxv=tree[rt].minv;
return;
}
int mid=(L+R)>>;
build(rt<<,L,mid);
build(rt<<|,mid+,R);
pushUp(rt);
} void query(int rt,int l,int r,int L,int R){
if(l<=L && R<=r){
small=min(small,tree[rt].minv);
bigger=max(bigger,tree[rt].maxv);
return;
}
int mid=(L+R)>>;
if(r<=mid)
query(rt<<,l,r,L,mid);
else if(l>mid)
query(rt<<|,l,r,mid+,R);
else{
query(rt<<,l,r,L,mid);
query(rt<<|,l,r,mid+,R);
}
}
int main()
{
int idx=;
scanf("%d%d",&n,&k);
build(,,n);
for(int i=;i<=n-k+;i++){
bigger=-INF;
small=INF;
query(,i,i+k-,,n);
minans[idx]=small; //存储最小值序列
maxans[idx]=bigger; //存储最大值序列
idx++;
}
for(int i=;i<idx;i++){
if(i==)
printf("%d",minans[i]);
else
printf(" %d",minans[i]);
}
printf("\n");
for(int i=;i<idx;i++){
if(i==)
printf("%d",maxans[i]);
else
printf(" %d",maxans[i]);
}
printf("\n");
return ;
}
单调队列:
#include <iostream>
#include <stdio.h>
/*
AC 5204ms
利用单调队列,分两次处理,第一次求最小值序列,第二次求最大值序列。 以求最小值序列为例:
先处理前k-1个元素,每次从队尾加入队列之前,先与队尾元素比较,若比队尾元素值小,则删去队尾元素,直到有比它小的,或者队列为空,
将该元素插入到队尾。即每次保证队列为单调非减队列,队首元素始终是队列中最小的。 接下来依次读入一个元素,与队尾元素比较,若队尾元素大,则删去队尾元素,直至遇到比要插入的元素小或者队列为空为止,插入该元素。
由于要求的是连续的k个区间,所以还要把队列中在该区间之前的元素删去。
这里有个技巧,也就是队列中,存储的不是元素值,而是在数组中的位置,这样很容易判断某个元素是否在连续的k个区间内,
获取元素值的话,就通过存储的数组下标获取。 求最大值序列的时候,同最小值序列,保证队列为非增队列,即队列的首个元素一定是最大的。 */
using namespace std;
const int maxn=;
int n,k;
int a[maxn]; //n个元素值
int dequeue[maxn]; //单调队列
//求最小值序列
void minans(int k,int n) {
int head=;
int tail=;
//先处理前k-1个元素
for(int i=; i<k-; i++) {
while(head<=tail && a[dequeue[tail]]>=a[i]) {
tail--;
}
tail++;
dequeue[tail]=i; //存储的是元素在a中的索引
}
for(int i=k-; i<n; i++) {
while(head<=tail && a[dequeue[tail]]>=a[i]) {
tail--;
}
tail++;
dequeue[tail]=i;
while(dequeue[head]<i-k+) //将索引在i-k+1之前的元素删去
head++;
printf("%d ",a[dequeue[head]]); //输出队列首个元素,即最小的元素 }
}
//求最大值序列
void maxans(int k,int n) {
int head=;
int tail=;
for(int i=; i<k-; i++) {
while(head<=tail && a[dequeue[tail]]<=a[i]) {
tail--;
}
tail++;
dequeue[tail]=i;
}
for(int i=k-; i<n; i++) {
while(head<=tail && a[dequeue[tail]]<=a[i]) {
tail--;
}
tail++;
dequeue[tail]=i;
while(dequeue[head]<i-k+)
head++;
printf("%d ",a[dequeue[head]]); }
} int main() {
scanf("%d%d",&n,&k);
for(int i=; i<n; i++) {
scanf("%d",&a[i]);
}
minans(k,n);
printf("\n");
maxans(k,n);
//printf("\n");
return ;
}
POJ 2823 Sliding Window (线段树/单调队列)的更多相关文章
- POJ 2823 Sliding Window 线段树
http://poj.org/problem?id=2823 出太阳啦~^ ^被子拿去晒了~晚上还要数学建模,刚才躺在床上休息一下就睡着了,哼,还好我强大,没有感冒. 话说今年校运会怎么没下雨!!!说 ...
- POJ 2823 Sliding Window 线段树区间求和问题
题目链接 线段树区间求和问题,维护一个最大值一个最小值即可,线段树要用C++交才能过. 注意这道题不是求三个数的最大值最小值,是求k个的. 本题数据量较大,不能用N建树,用n建树. 还有一种做法是单调 ...
- POJ 2823 Sliding Window 再探单调队列
重新刷这个经典题,感觉跟以前不一样了,变得更加容易理解了,不讲解了,看代码.注意:要用C++提交,用G++会超时.. 代码: #include <iostream> #include &l ...
- PKU 2823 Sliding Window(线段树||RMQ||单调队列)
题目大意:原题链接(定长区间求最值) 给定长为n的数组,求出每k个数之间的最小/大值. 解法一:线段树 segtree节点存储区间的最小/大值 Query_min(int p,int l,int r, ...
- POJ 2823 Sliding Window + 单调队列
一.概念介绍 1. 双端队列 双端队列是一种线性表,是一种特殊的队列,遵守先进先出的原则.双端队列支持以下4种操作: (1) 从队首删除 (2) 从队尾删除 (3) 从队尾插入 (4) ...
- POJ 2823 Sliding Window 题解
POJ 2823 Sliding Window 题解 Description An array of size n ≤ 106 is given to you. There is a sliding ...
- 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)
To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...
- 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP
2892: 强袭作战 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 45 Solved: 30[Submit][Status][Discuss] D ...
- BZOJ 1012 线段树||单调队列
非常裸的线段树 || 单调队列: 假设一个节点在队列中既没有时间优势(早点入队)也没有值优势(值更大),那么显然不管在如何的情况下都不会被选为最大值. 既然它仅仅在末尾选.那么自然能够满足以上的条件 ...
随机推荐
- java检测端口号是否配占用
java检测端口号是否被占用的工具类: package com.frank.util; import java.io.IOException; import java.net.InetAd ...
- ArcGIS10中matplotlib画图时的中文设置
利用GIS的数据批量生成XY的图形图像文件,可以直接使用Python.一般大家都是用matplotlib,中文设置的问题参看了许多内容,结论是对错不一,让我折腾了三天,现总结如下: 1.软件的版本.安 ...
- Java RMI 远程方法调用
Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...
- cookie+session,会话时间设定
很多Web程序中第一次登录后,在一定时间内(如2个小时)再次访问同一个Web程序时就无需再次登录,而是直接进入程序的主界面(仅限于本机). 实现这个功能关键就是服务端要识别客户的身份.而用Cookie ...
- picLazyLoad 图片延时加载,包含背景图片
/** * picLazyLoad 图片延时加载,包含背景图片 * $(img).picLazyLoad({...}) * data-original 预加载图片地址 * alon */ ;(func ...
- 而在Jquery中则使用$.map()、$.each()来操作数组
首先是普通的数组(索引为整数的数组): //$.map(arr,fn); //对数组中的每个元素调用fn函数逐个进行处理,fn函数将处理返回最后得到的一个新的数组 var arr = [9, 8, 7 ...
- Excel REPT函数使用
需要制作1K大小的数据 使用Excel REPT函数可以迅速制造 Excel REPT 函数 =REPT(1,1024) 结果直接黏贴进txt文件,注意删除尾空格.
- RaddioButton控件
<GroupBox Margin="5"> <StackPanel> <RadioButton IsChecked="true"& ...
- nginx学习之一
http://tengine.taobao.org/book/chapter_02.html
- mysql5.5 Replication 主从同步
mysql5.5 Replication 主从同步 ------------------[主]------------------[mysqld]server-id=1 log-bin=mysql-b ...