poj2823 区间内最值的不同解法
来源:互联网 发布:电脑压力测试软件 编辑:程序博客网 时间:2024/05/28 04:52
题目大意:给定一个n个数的数列,从左至右输出每个长度为m的数列段内的最大/小数。
然后这题到底有什么解法呢?
解法1
这道题的标解肯定是单调队列啦,挺好写,当时好像就是这道题是单调队列的入门来着,时间复杂度O(n)
具体的我就不讲了
#include<cstdio>#include<cstring>const int N=1000005;int n,m;int s[N];int st,ed;int q[N],wei[N];void getmin (){ st=1;ed=0; for (int u=1;u<m;u++) { while (st<=ed&&q[ed]>=s[u]) ed--; ed++;q[ed]=s[u];wei[ed]=u; } for (int u=m;u<=n;u++) { while (st<=ed&&q[ed]>=s[u]) ed--; ed++;q[ed]=s[u];wei[ed]=u; /*for (int i=st;i<=ed;i++) printf("%d ",q[i]); printf("\n");*/ while (wei[st]<u-m+1) st++; printf("%d ",q[st]); } printf("\n");} void getmax (){ st=1;ed=0; for (int u=1;u<m;u++) { while (st<=ed&&q[ed]<=s[u]) ed--; ed++;q[ed]=s[u];wei[ed]=u; } for (int u=m;u<=n;u++) { while (st<=ed&&q[ed]<=s[u]) ed--; ed++;q[ed]=s[u];wei[ed]=u; while (wei[st]<u-m+1) st++; printf("%d ",q[st]); } printf("\n");}int main(){ scanf("%d%d",&n,&m); for (int u=1;u<=n;u++) scanf("%d",&s[u]); getmin();getmax(); return 0;}
解法2
于是今天由于scy的要求,我又要做一次。。单调队列太无聊了,我们来想一想别的做法
我们可以吧他看做若干个(m-n)个询问,每次就问一个区间的最大(小)值,这就好办了!我们可以对序列进行分块,然后跑,复杂度
#include<cstdio>#include<cmath>const int N=200005;const int MAX=1<<30;int n,m;int L[N],R[N],belong[N],cnt;int a[N];int t[N];void prepare ()//预处理分块 { int nn=sqrt(n);L[1]=1;cnt=1; for (int u=1;u<=n;u++) { belong[u]=cnt; if (u%nn==0) { R[cnt]=u; cnt++; L[cnt]=u+1; } } cnt=belong[n]; R[cnt]=n; for (int u=1;u<=cnt;u++) t[u]=-MAX; return ;}int mymax (int x,int y) {return x>y?x:y;}int ask (int l,int r){ int lalal=-MAX; if (belong[l]==belong[r]) { for (int u=l;u<=r;u++) lalal=mymax(lalal,a[u]); } else { for (int u=l;u<=R[belong[l]];u++) lalal=mymax(lalal,a[u]); for (int u=belong[l]+1;u<belong[r];u++) lalal=mymax(lalal,t[u]); for (int u=L[belong[r]];u<=r;u++) lalal=mymax(lalal,a[u]); } return lalal;}int main(){ scanf("%d%d",&n,&m);m--; prepare(); for (int u=1;u<=n;u++) { scanf("%d",&a[u]); t[belong[u]]=mymax(t[belong[u]],a[u]); } for (int u=1;u<=n;u++) { if (u+m>n) break; printf("%d\n",ask(u,u+m)); } return 0;}
解法三
和解法二差不多,不过我们的最值问题可以用线段树来维护一下,然后时间复杂度是
解法四
假如我们看做势若干个询问的话,我们其实可以考虑莫队。。其实已经排好序的啦,并不需要什么操作,好想复杂度都是从n根号n变为线性了。。然后怎么维护呢,我们可以对数离散化,然后维护权值线段树就好了。。到时候询问就跑就好了,时间复杂度是
解法五
哦,对了,做了解法二都忘了RMQ了。。思路和分块是一样的,但是时间复杂度是
解法六
poj的讨论上面发现的
这题用C++ STL的priority_queue同时维护一个最大堆和一个最小堆就过了
我想了一下,也可以,就维护一个堆嘛。。然后你每次超出范围的数就删掉。。怎么删呢,可以打标记,到时候再跳过。我对堆也不是很熟,但当时研究左偏树的时候知道这玩意是可以
解法七
我暂时只想到这么多啦!要是还有就是暴力加玄学优化啦!
阅读全文
0 0
- poj2823 区间内最值的不同解法
- POJ2823 - 线段树求区间的最值..
- fibonacci 的不同解法
- 求最大公约数的不同解法
- 区间DP 的两种解法
- 3303 翻转区间 伸展树的解法
- POJ2823(线段树求区间最值)
- 区间的不同实现方式
- poj2823
- POJ2823
- poj2823
- poj2823
- POJ2823
- poj2823
- poj2823
- POJ2823
- poj2823
- POJ2823
- 11、数字颠倒
- 7.10noip测试
- 功率放大电路比较
- poj3228
- Https协议详解
- poj2823 区间内最值的不同解法
- 从键盘接收一个文件夹路径,统计该文件夹大小
- [随心译]2017.8.2-Win10将包含内置的眼球追踪系统
- hdu2160 母猪的故事(C语言)
- 【环境准备】centos 6.5 安装redis 源码安装
- 【PAT】【Advanced Level】1038. Recover the Smallest Number (30)
- 王者系列之springMVC
- c语言关键字简略解读
- codeforces55D(离散化数位dp)