2019年杭电多校第二场 1002题Beauty Of Unimodal Sequence(LIS+单调栈)
题目链接
思路
首先我们对\(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+单调栈)的更多相关文章
- 2019年杭电多校第二场 1008题Harmonious Army(HDU6598+最小割+建图)
题目链接 传送门 题意 有\(n\)个士兵,要你给他们分配职业.有\(m\)对关系,对于某一对关系\(u,v\),如果同为勇士则总能力增加\(a\),同法师则增加\(c\),一个勇士一个法师增加\(\ ...
- 2019年杭电多校第二场 1012题Longest Subarray(HDU6602+线段树)
题目链接 传送门 题意 要你找一个最长的区间使得区间内每一个数出现次数都大于等于\(K\). 思路 我们通过固定右端点考虑每个左端点的情况. 首先对于每个位置,我们用线段树来维护它作为\(C\)种元素 ...
- 2019年杭电多校第一场 1002题Operation(HDU6579+线性基)
题目链接 传送门 题意 初始时有\(n\)个数,现在有\(q\)次操作: 查询\([l,r]\)内选择一些数使得异或和最大: 在末尾加入一个数. 题目强制在线. 思路 对于\(i\)我们记录\([1, ...
- Rikka with Travels(2019年杭电多校第九场07题+HDU6686+树形dp)
目录 题目链接 题意 思路 代码 题目链接 传送门 题意 定义\(L(a,b)\)为结点\(a\)到结点\(b\)的路径上的结点数,问有种\(pair(L(a,b),L(c,d))\)取值,其中结点\ ...
- 2019年杭电多校第一场 1009题String(HDU6586+模拟+单调栈)
题目链接 传送门 题意 给你一个字符串,要你构造一个长为\(k\)的子串使得每个字母出现的次数在\([L_i,R_i](0\leq i\leq26)\)间且字典序最小. 思路 做这种题目就是要保持思路 ...
- 2019年杭电多校第一场 1004题Vacation(HDU6581+数学)
题目链接 传送门 题意 有\(n+1\)辆车要过红绿灯,告诉你车的长度.与红绿灯的起点(题目假设红绿灯始终为绿).车的最大速度,问你第\(0\)辆车(距离最远)车头到达红绿灯起点的时间是多少(每辆车最 ...
- 2019年牛客多校第二场 H题Second Large Rectangle
题目链接 传送门 题意 求在\(n\times m\)的\(01\)子矩阵中找出面积第二大的内部全是\(1\)的子矩阵的面积大小. 思路 处理出每个位置往左连续有多少个\(1\),然后对每一列跑单调栈 ...
- 2019杭电多校第二场hdu6601 Keen On Everything But Triangle
Keen On Everything But Triangle 题目传送门 解题思路 利用主席树求区间第k小,先求区间内最大的值,再求第二大,第三大--直到找到连续的三个数可以构成一个三角形.因为对于 ...
- 2019杭电多校第二场hdu6602 Longest Subarray(线段树)
Longest Subarray 题目传送门 解题思路 本题求一个最大的子区间,满足区间内的数字要么出现次数大于等于k次,要么没出现过.给定区间内的数字范围是1~c. 如果r为右边界,对于一种数字x, ...
随机推荐
- 本地VS调试服务器 IIS 程序
由于读书的关系,毕业后选择在武汉,工作三年,至今年5月份挪窝到沿海某二线城市,换城市相当于裸辞,一切从头开始,新的城市,新的居住地,新的空气,新工作,新挑战.一直忙忙碌碌,孜孜不倦的汲取着,担心脱队, ...
- Makefile文件基本格式
以下是Makefile的基本模板 #指定编译器CC = g++#指定编译参数CFLAGS = -std=c++11 #指定头文件路径,此处用于指定非标准库的头文件路径INC = -I./ -I /us ...
- Java基础之十六 数组
数组:可以创建并组装它们,通过使用整型索引值访问它们的元素,并且它们的尺寸不能改变. 16.1 数组为什么特殊 数组与其他种类的容器之间的区别有三方面:效率,类型和保存基本类型的能力. 数组是一种效率 ...
- elasticsearch 常用命令 一直红色 重启不稳定 不停的宕机
persistent (重启后设置也会存在) or transient (整个集群重启后会消失的设置). 查看集群状态和每个indices状态.搜索到red的,没用就删除 GET /_cluster/ ...
- Java并发之多线程下竞态条件概念的理解
一.简述 竞态条件(Race Condition):计算的正确性取决于多个线程的交替执行时序时,就会发生竞态条件. 二.常见竞态条件分析 最常见的竞态条件为 1.先检测后执行 执行依赖于检测的结果,而 ...
- [.Net,C#]三类资源:流对象Stream,字节数组byte[],图片Image
三类资源:流对象Stream,字节数组byte[],图片Image 关系:Stream<=>byte[],byte[]<=>Image Stream 与Image相互转化的媒介 ...
- 使用 KVO 可能会拖慢启动速度
问题  在某一次启动速度优化中,发现最开始的某个 runLoop 中,一个runLoop 耗时很长.发现一个 KVO 变量的初始化消耗了13ms之久,这对启动速度是不可接受了. 源码分析 用 Ins ...
- LongAdder源码分析
AtomicLong是作用是对长整形进行原子操作,显而易见,在java1.8中新加入了一个新的原子类LongAdder,该类也可以保证Long类型操作的原子性,相对于AtomicLong,LongAd ...
- 第十二节:Asp.Net Core 之分布式缓存(SQLServer和Redis)
一. 整体说明 1. 说明 分布式缓存通常是指在多个应用程序服务器的架构下,作为他们共享的外部服务共享缓存,常用的有SQLServer.Redis.NCache. 特别说明一下:这里的分布式是 ...
- C#调用 kernel32.dll
调用方法: private string mFileName; //INI文件名 public OneGanttINI(string pFileName) { this.mFileName = App ...