HDU 3530 Subsequence
這道題很有意思,需要巧妙地套用單調隊列
首先我們要明確幾件事情
1.假設我們現在知道序列(i,j)是符合標準的,那么如果第j+1個元素不比(i,j)最大值大也不比最小值小,那么(i,j+1)也是合法的
2.如果(i,j)不合法的原因是差值比要求小,那在(i,j)范圍內的改動是無效的,需要加入j+1元素充當最大值或者最小值才可能獲得合法的序列
3.假設序列(i,j)的差值比要求大,那么我們必須將其中的最大值或者最小值從序列中刪除出去,才可能獲得一個合法的序列,只往里加入元素是不可能令序列合法的
基于以上幾點考慮,我們可以利用單調隊列完成我們的算法。
設定一個變量ST作為當前合法序列的開端(對于一個序列(i,j),其對應的ST為i-1),初始值是0
設f[i]是以第i個元素結尾的最長合法序列長度,我們把i加入兩個單調隊列中維護,一個維護i之前的最小值,一個是最大值。
情況1.如果最大值和最小值的差值在范圍之內,那么(ST,i)是合法序列,f[i]=i-ST。
情況2.如果差值比要求小,則沒有以i結尾的合法序列,f[i]=0。
情況3.如果差值比要求大,那么需要刪除最大值或者最小值,怎么刪除?當然是刪除最大值和最小值中靠前的那個,同時ST相應更新,直到情況1或者情況2。
代碼:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
typedef pair<int,int> PII;
const int N=1000010;
int n,m,k;
int a[N];
int ans=0;
struct MonQ{
????PII q[N];
????int st,ed;
????void clear() {
????????st=ed=0;
????}
????void popto(int x){
????????while(ed-st>=1 && q[st].second<x) st++;
????}
????void maintain(int mode) {
????????if(mode==0) {
????????????while(ed-st>=2 && q[ed-1]>=q[ed-2]) q[ed-2]=q[ed-1],ed--;
????????}else {
????????????while(ed-st>=2 && q[ed-1]<=q[ed-2]) q[ed-2]=q[ed-1],ed--;
????????}
????}
????void push(int x,int p){
????????q[ed++]=PII(x,p);
????}
????bool empty(){
????????return st==ed;
????}
????int top() {
????????if(ed-st>=1) return q[st].first;
????????else return 0;
????}
????int label() {
????????return q[st].second;
????}
}q1,q2;
int main() {
????while(scanf("%d%d%d",&n,&m,&k)!=EOF) {
????????for(int i=0;i<n;i++) scanf("%d",&a[i]);
????????int st=0;
????????ans=0;
????????q1.clear();
????????q2.clear();
????????for(int i=0;i<n;i++) {
????????????q1.push(a[i],i);
????????????q2.push(a[i],i);
????????????q1.maintain(0);
????????????q2.maintain(1);
????????????int diff=q1.top()-q2.top();
????????????if(diff>=m && diff<=k){
????????????????ans=max(ans,i-st+1);
????????????}
????????????while(diff>k && !q1.empty() && !q2.empty()) {
????????????????int topop=min(q1.label(),q2.label());
????????????????st=topop+1;
????????????????q1.popto(st);
????????????????q2.popto(st);
????????????????diff=q1.top()-q2.top();
????????????}
????????}
????????printf("%d\n",ans);
????}
????return 0;
}
?
轉載于:https://www.cnblogs.com/programCaiCai/archive/2012/08/30/HDU3530.html
總結
以上是生活随笔為你收集整理的HDU 3530 Subsequence的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 饥饿游戏(三部曲)
- 下一篇: 越狱插件推荐:来电归属地KuaiDial