P3411 序列变换 [单调队列]

序 列 变 换 序列变换

题目描述见链接 .


正 解 部 分 \color{red}{正解部分}

题目转化 为: 求数列中离散化后 最长连续不间断子序列 的长度 l e n len len, a n s = N − l e n ans = N-len ans=Nlen .

子序列需要满足 3 3 3 个条件 ↓ \downarrow

  • 编号 单调递增 .
  • 子序列中的值 连续 .
  • 子序列中的值 单调不减 .

可以使用 单调队列 维护 .


实 现 部 分 \color{red}{实现部分}

将所有相同的数字使用 std::vector<int> 存储其位置,

按值 从小到大 加入队列, 对于相同的值, 按位置 从大到小 加入队列 .


  • 当相同值的其中一个位置可以加入队列, 比它大的位置也可以加入队列 .

若当前加入 灰色柱子, 红色柱子 的位置比 灰色柱子 大,
因此要弹掉 红色柱子, 而弹掉 红色柱子后直接加入 灰色柱子 会使得序列不满足 条件 2 2 2,
因此要弹掉所有值 小于 红色柱子 的 柱子 .

#include<bits/stdc++.h>
#define reg register
#define pb push_back

int read(){
        char c;
        int s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ flag = -1, c = getchar(); break ; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

const int maxn = 1e6 + 5;

int N;
int Mx;
int Ans;
int A[maxn];

std::deque <int> Q;
std::vector <int> B[maxn];

int main(){
        Ans = N = read();
        for(reg int i = 1; i <= N; i ++) A[i] = read(), B[A[i]].pb(i), Mx = std::max(Mx, A[i]);
        for(reg int i = 1; i <= Mx; i ++){ // 大小
                int size = B[i].size();
                for(reg int j = size-1; ~j; j --){
                        int pos = B[i][j];
                        while(!Q.empty() && Q.back() > pos){ // 位置
                                while(Q.size() >= 2 && A[Q.front()] < A[Q.back()]) Q.pop_front(); // 连续
                                Q.pop_back();
                        }
                        Ans = std::min(Ans, N-(int)Q.size()-(size-j));
                }
                for(reg int j = 0; j < size; j ++) Q.push_back(B[i][j]);
        }
        printf("%d\n", Ans);
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值