题目链接

传送门

思路

首先我们对\(a\)正反各跑一边\(LIS\),记录每个位置在前一半的\(LIS\)中应该放的位置\(ans1[i]\),后一半的位置\(ans2[i]\)。

对于字典序最小的方案,我们找到第一个峰值,然后往前遍历。在\(i\)这个位置,如果它在\(LIS\)中放的位置是\(pos\),那么我们先看当前放在\(pos+1\)的值是否比它大,大的话就说明这个位置一定比前面放过在\(pos\)这个位置的更优(因为字典序更小,且\([1,i]\)一定可以放满\([1,pos-1]\)),然后我们就用单调栈把当前放的小于等于\(pos\)的值全部\(pop\)掉。对于后一半的我们就直接对于每个可以放的位置反复覆盖即可。

对于字典序最大的我们则就是前一半反复覆盖,后一半用单调栈维护,与字典序刚好相反。

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL; #define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0) const double eps = 1e-8;
const int mod = 998244353;
const int maxn = 3e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL; int n;
stack<int> st;
vector<int> vec, v;
int pos[maxn];
int a[maxn], dp[maxn], ans1[maxn], ans2[maxn]; int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
while(~scanf("%d", &n)) {
memset(dp, inf, sizeof(dp));
dp[0] = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
ans1[i] = ans2[i] = 0;
pos[i] = inf;
ans1[i] = lower_bound(dp + 1, dp + n + 1, a[i]) - dp;
dp[ans1[i]] = a[i];
}
memset(dp, inf, sizeof(dp));
dp[0] = 0;
for(int i = n; i >= 1; --i) {
ans2[i] = lower_bound(dp + 1, dp + n + 1, a[i]) - dp;
dp[ans2[i]] = a[i];
}
while(!st.empty()) st.pop();
int idx = 1, mx = ans1[1] + ans2[1];
for(int i = 2; i <= n; ++i) {
if(ans1[i] + ans2[i] > mx) {
idx = i;
mx = ans1[i] + ans2[i];
}
}
pos[ans1[idx]] = a[idx];
for(int i = idx - 1; i >= 1; --i) {
if(ans1[i] >= ans1[idx]) continue;
if(pos[ans1[i]+1] <= a[i]) continue;
while(!st.empty() && ans1[i] >= ans1[st.top()]) {
pos[ans1[st.top()]] = inf;
st.pop();
}
st.push(i);
pos[ans1[i]] = a[i];
}
vec.clear();
while(!st.empty()) {
vec.push_back(st.top());
st.pop();
}
vec.push_back(idx);
int las = idx;
for(int i = idx + 1; i <= n; ++i) {
if(ans2[i] == ans2[las] - 1 && a[i] < a[las]) {
vec.push_back(i);
las = i;
}
}
int flag = 0;
for(auto x:vec) {
if(flag) printf(" ");
flag = 1;
printf("%d", x);
}
printf("\n"); vec.clear();
idx = 1, mx = ans1[1] + ans2[1];
for(int i = 2; i <= n; ++i) {
if(ans1[i] + ans2[i] >= mx) {
idx = i;
mx = ans1[i] + ans2[i];
}
}
las = idx;
vec.push_back(idx);
for(int i = idx - 1; i >= 1; --i) {
if(ans1[i] == ans1[las] - 1 && a[i] < a[las]) {
vec.push_back(i);
las = i;
}
}
reverse(vec.begin(), vec.end());
for(int i = 1; i<= n; ++i) pos[i] = inf;
pos[ans2[idx]] = a[idx];
while(!st.empty()) st.pop();
for(int i = idx + 1; i <= n; ++i) {
if(ans2[i] > ans2[idx]) continue;
if(a[i] >= pos[ans2[i]+1]) continue;
while(!st.empty() && ans2[i] >= ans2[st.top()]) {
pos[ans2[st.top()]] = inf;
st.pop();
}
st.push(i);
pos[ans2[st.top()]] = a[i];
}
v.clear();
while(!st.empty()) {
v.push_back(st.top());
st.pop();
}
reverse(v.begin(), v.end());
flag = 0;
for(auto x:vec) {
if(flag) printf(" ");
flag = 1;
printf("%d", x);
}
for(auto x:v) {
if(flag) printf(" ");
flag = 1;
printf("%d", x);
}
printf("\n");
}
return 0;
}

2019年杭电多校第二场 1002题Beauty Of Unimodal Sequence(LIS+单调栈)的更多相关文章

  1. 2019年杭电多校第二场 1008题Harmonious Army(HDU6598+最小割+建图)

    题目链接 传送门 题意 有\(n\)个士兵,要你给他们分配职业.有\(m\)对关系,对于某一对关系\(u,v\),如果同为勇士则总能力增加\(a\),同法师则增加\(c\),一个勇士一个法师增加\(\ ...

  2. 2019年杭电多校第二场 1012题Longest Subarray(HDU6602+线段树)

    题目链接 传送门 题意 要你找一个最长的区间使得区间内每一个数出现次数都大于等于\(K\). 思路 我们通过固定右端点考虑每个左端点的情况. 首先对于每个位置,我们用线段树来维护它作为\(C\)种元素 ...

  3. 2019年杭电多校第一场 1002题Operation(HDU6579+线性基)

    题目链接 传送门 题意 初始时有\(n\)个数,现在有\(q\)次操作: 查询\([l,r]\)内选择一些数使得异或和最大: 在末尾加入一个数. 题目强制在线. 思路 对于\(i\)我们记录\([1, ...

  4. Rikka with Travels(2019年杭电多校第九场07题+HDU6686+树形dp)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 定义\(L(a,b)\)为结点\(a\)到结点\(b\)的路径上的结点数,问有种\(pair(L(a,b),L(c,d))\)取值,其中结点\ ...

  5. 2019年杭电多校第一场 1009题String(HDU6586+模拟+单调栈)

    题目链接 传送门 题意 给你一个字符串,要你构造一个长为\(k\)的子串使得每个字母出现的次数在\([L_i,R_i](0\leq i\leq26)\)间且字典序最小. 思路 做这种题目就是要保持思路 ...

  6. 2019年杭电多校第一场 1004题Vacation(HDU6581+数学)

    题目链接 传送门 题意 有\(n+1\)辆车要过红绿灯,告诉你车的长度.与红绿灯的起点(题目假设红绿灯始终为绿).车的最大速度,问你第\(0\)辆车(距离最远)车头到达红绿灯起点的时间是多少(每辆车最 ...

  7. 2019年牛客多校第二场 H题Second Large Rectangle

    题目链接 传送门 题意 求在\(n\times m\)的\(01\)子矩阵中找出面积第二大的内部全是\(1\)的子矩阵的面积大小. 思路 处理出每个位置往左连续有多少个\(1\),然后对每一列跑单调栈 ...

  8. 2019杭电多校第二场hdu6601 Keen On Everything But Triangle

    Keen On Everything But Triangle 题目传送门 解题思路 利用主席树求区间第k小,先求区间内最大的值,再求第二大,第三大--直到找到连续的三个数可以构成一个三角形.因为对于 ...

  9. 2019杭电多校第二场hdu6602 Longest Subarray(线段树)

    Longest Subarray 题目传送门 解题思路 本题求一个最大的子区间,满足区间内的数字要么出现次数大于等于k次,要么没出现过.给定区间内的数字范围是1~c. 如果r为右边界,对于一种数字x, ...

随机推荐

  1. Spring Cloud Greenwich.SR4 发布了,跟不上了……

    前几天 Spring Cloud Greenwich.SR4 发布了: https://spring.io/blog/2019/11/19/spring-cloud-greenwich-sr4-rel ...

  2. WeakhashMap源码1

    弱引用(WeakReference)的特性是:当gc线程发现某个对象只有弱引用指向它,那么就会将其销毁并回收内存.WeakReference也会被加入到引用队列queue中. 它的特殊之处在于 Wea ...

  3. 【剑指offer】数据流中的中位数

    题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值.我们 ...

  4. SQL Server 10分钟理解游标

    概述 游标是邪恶的! 在关系数据库中,我们对于查询的思考是面向集合的.而游标打破了这一规则,游标使得我们思考方式变为逐行进行.对于类C的开发人员来着,这样的思考方式会更加舒服. 正常面向集合的思维方式 ...

  5. [转帖]深度剖析一站式分布式事务方案 Seata-Server

    深度剖析一站式分布式事务方案 Seata-Server https://www.jianshu.com/p/940e2cfab67e 金融级分布式架构关注 22019.04.10 16:59:14字数 ...

  6. SpringBoot使用@ServerEndpoint无法依赖注入问题解决(WebSocket)

    如上两图所示,在WebSocket中我想使用Redis.把自己编写的RedisUtil使用@Autowired自动注入到当前类. 在运行时,出现异常:java.lang.NullPointExcept ...

  7. ubuntu docker 搭建 mongodb,开启授权访问 redis,mysql mssql 备份还原

    命令安装docker 如果您想从Ubuntu存储库安装docker版本,则可以运行下面的apt命令. sudo apt install docker.io等到安装完成后,您可以启动Docker并使用s ...

  8. python第五章程序练习题

    5.2 def isOdd(a): if a%2!=0: return True else: a=eval(input()) print(isOdd(a)) 5.3 def isNum(x): try ...

  9. C#写入Excel文件方式

    由于在工作中经常要把数据库的统计数据导入Excel文件,进行IO磁盘操作,所以在这里记录下. 首先创建默认文件夹,并返回文件夹路径. private static string CPath(strin ...

  10. CXF 教程(一)

    CXF Web Service 简单示例 1 准备工作 2 第一个例子 3 客户端 3.1 使用 WSDL 生成客户端 4 RPC 风格 5 相关命令介绍 5.1 Java to WS 1 准备工作 ...