题目


思路

1.需明确,在删除之后,最长连续递增子序列一定会存在在删除后两端连接处。下文用L代表最长连续递增子序列。
算法1:枚举起点j,终点i,再计算两点之间的L。O(n3)O(n3)O(n^3)
算法2:预先打表g(i),f(i),分别代表以i结尾和开头的最长L,再枚举i和j,可以用O(1)O(1)O(1)时间算出L。O(n2)O(n2)O(n^2)
算法3:只枚举终点i而不枚举起点j,通过一个STL set,查找最优j来避免枚举。O(nlogn)O(nlogn)O(nlogn)

2.具体方法:规定(A[i], g)为set中的元素,A[i]为序列中实际元素值,g就是g(i),并由A[i]升序排序。

  • A[i]存在的目的是,若要构成连续子序列,则起点j的元素值必须小于终点i的。
  • 删减元素:对于A[i2]<=A[i1]且g[i2]>g[i1]A[i2]<=A[i1]且g[i2]>g[i1]A[i_2]g[i_1]的i1i1i_1,可以进行删除。原因是,i2i2i_2比i1i1i_1对终点元素值的要求更小,并且L更大。

枚举终点i时,只需要在set中lower_bound找到满足A[j] < A[i]的最大A[j]即可,原因是根据上面的删减规则,A[x]越大一定有g[x]越大。

代码

#include <cstdio>
#include <cstdlib>
#include <set>
#include <algorithm>
#define _for(i, a, b) for (int i = (a); i < (b); i++)
#define _rep(i, a, b) for (int i = (a); i <= (b); i++)
using namespace std;const int maxn = 200000 + 1000;
struct node {int a, g;node(int a, int g) :a(a), g(g) {}   // 带参构造函数的写法bool operator < (const struct node &rhs) const {return a < rhs.a;}
};
int A[maxn], n, ans, G[maxn], F[maxn];
set<node> B;int main() {//freopen("input.txt", "r", stdin);//freopen("output.txt", "w", stdout);int T;scanf("%d", &T);while (T--) {scanf("%d", &n);_for(i, 0, n) scanf("%d", &A[i]);G[0] = 1;_for(i, 1, n) {if (A[i] > A[i - 1]) G[i] = G[i - 1] + 1;else G[i] = 1;}F[n-1] = 1;for (int i = n - 2; i >= 0; i--) {if (A[i] < A[i + 1]) F[i] = F[i + 1] + 1;else F[i] = 1;}ans = 1;B.clear();B.insert(node(A[0], G[0]));_for(i, 1, n) {node now(A[i], G[i]);set<node>::iterator iter = B.lower_bound(now);bool keep = true;if (iter != B.begin()) {--iter;ans = max(ans, F[i] + iter->g);   //学会对iterator直接进行操作if (iter->g >= now.g) keep = false;}if (keep) {iter = B.insert(now).first;if (iter != B.end()) {for (++iter; iter != B.end();) {if (now.g >= iter->g && now.a < iter->a) B.erase(iter++);   // 此处a<a是为了防止等于发生?else break;}}}}printf("%d\n", ans);}return 0;
}

码力技巧

1.struct的构造函数的写法:

struct node {int a, g;node(int a, int g) :a(a), g(g) {}   // 带参构造函数的写法bool operator < (const struct node &rhs) const {return a < rhs.a;}
};

2.aoapc习题选解,陈锋大佬教给的for循环宏定义:

#define _for(i, a, b) for (int i = (a); i < (b); i++)
#define _rep(i, a, b) for (int i = (a); i <= (b); i++)

使用起来

_for(i, 0, n) scanf("%d", &A[i]);

可能还是有一点增加代码易读性的功能的吧。。。
反正我只见他的代码这样写过。。

本题资源

此题是 ACM/ICPC Central European Regional Contest 区域赛的题,我找到了官方题解和数据,拿给大家用啦:
http://cerc10.ii.uni.wroc.pl/solutions.html
data

废话

1.卡了我半个月的题。。终于过了。。至于为什么能卡我半个月,说不上来。这道题吧,说难也不难,特别是LRJ已经清清楚楚地把思路讲出来了,不过是稍抽象一点。还是码力不够,做题做得少。而且应该了解到,一定要思路想的清清楚楚再去写代码,我之前做的时候,是把set整个都做完以后,才从1开始枚举i,这样就导致我还必须去判断一下终点i的位置是不是在起点j后面,不然就逻辑错误导致花式WA。最后一看LRJ的代码,明明set和枚举i可以在一个循环里同时做。。。
2.而且之前程序虽然绕,但整体都对,出了g(i)和f(i)的求法。但我全程都以为,这么简单的两个打表我怎么能错。。而且错的还很隐晦(现在都不知道那种是怎么错的)。。导致一直忽略这两个打表的debug,一直在枚举i和set上下功夫,下了半天没用的功夫。。
之前的打表代码,懒得看为啥错了。。。

int s = 0; G[0] = 1;
_for(i, 1, n) {if (A[i] < A[i - 1]) {s = i;G[i] = 1;}else G[i] = i - s + 1;
}
s = n - 1; F[n - 1] = 1;
for (int i = n - 2; i >= 0; i--) {if (A[i] > A[i + 1]) {s = i;F[i] = 1;}else F[i] = s - i + 1;
}

[数据结构] UVa1471 Defense Lines 防线相关推荐

  1. UVA 1471 Defense Lines 防线

    https://vjudge.net/problem/UVA-1471 给一个长度为n的序列,要求删除一个连续子序列,使剩下的序列有一个长度最大的连续递增子序列. 例如  Sample Input 2 ...

  2. UVA 1471 Defense Lines 防线 (LIS变形)

    给一个长度为n的序列,要求删除一个连续子序列,使剩下的序列有一个长度最大的连续递增子序列. 最简单的想法是枚举起点j和终点i,然后数一数,分别向前或向后能延伸的最长长度,记为g(i)和f(i).可以先 ...

  3. uva1471 Defense Lines

    题意:给一个长度为n(n<=200000)的序列,删掉某一个连续的序列,使得剩下的序列有一个长度最大的连续递增子序列. 思路:首先这里最容易想到,枚举任意两个点j,i,删掉从j到i的序列,求剩下 ...

  4. UVa1471 Defense Lines(LIS变形)

    题目链接 1.题目描述:给定一个长度为n的序列,现在可以删除一段任意长度的子序列,使得删除后剩下的序列中有长度最大的连续递增子序列 2.这个题目很新颖,刚开始看裸写了一个LIS,一看样例过了兴致勃勃的 ...

  5. uva 1471 Defense Lines

    题目大意:给定一串数字序列,然后叫你删除连续一部分序列,然后使得剩下的序列中存在的连续的最大增长序列长度是多少 . . // // main.cpp // uva UVa1471 Defense Li ...

  6. uva 1471 Defense Lines

    题目:https://vjudge.net/problem/UVA-1471 题意:  lrj思路:第一思路可以暴力枚举,先枚举i(i=1:len),i往右数,看以i开头的最大升序序列个数.然后再枚举 ...

  7. UVa 1471 Defense Lines (解释紫书思路)

    题目链接:https://cn.vjudge.net/problem/UVA-1471 设序列L表示连续递增子序列: 则最长的L就可以分为两部分,一部分是以j结尾的序列,另一部分是以i为开头的序列 现 ...

  8. uva 1471 Defense Lines (降低复杂度)

    题意: 给一个长度为n(n <= 200000) 的序列,你删除一段连续的子序列,使得剩下的序列拼接起来,有一个最长的连续递增子序列 思路: 设f[i] 和g[i] 分别表示 以i为开始 和 以 ...

  9. UVA 1471 Defense Lines (LIS变形)

    题意:删除原序列中的一段连续子序列,使得剩下的序列中存在一段最长连续子序列. 题解:LIS变形 我们用l[i]l[i]l[i]和r[i]r[i]r[i]记录往右以iii结尾和往左以iii开头的最长连续 ...

最新文章

  1. alert和console的区别
  2. 关于html以及js相关格式验证的记录
  3. Spring Cloud实战小贴士:健康检查
  4. 虚拟机VMware Workstation安装Linux服务器Debian11系统详细教程
  5. 浅谈PHP面向对象编程(五)
  6. 无线桥接和中继模式的区别
  7. 内存优化-service优化
  8. 计算机组成原理cu_计算机组成原理19----控制单元CU设计
  9. git 上查找一行代码的提交记录
  10. 冰柱图分析:学习笔记
  11. ECCV2020 TIDE: A General Toolbox for Identifying Object Detection Errors
  12. 期中计算机网络答案,计算机网络基础自考试题「附答案」
  13. 一闪一闪亮晶晶,满屏都是小星星
  14. q87芯片组支持的服务器CPU,采用英特尔® Q87 芯片组的第四代智能英特尔® 酷睿™ 处理器...
  15. Apipost产品介绍
  16. 王道论坛机试指南学习笔记(四)图论
  17. 制造企业如何满足客户需求?精益生产教您三招
  18. 养心殿新发现“除夕戏目折”在北京故宫午门展出
  19. 人脸课堂签到管理系统(总结二) 摄像头显示
  20. html标签手册 360doc,360doc网文摘手

热门文章

  1. 天气预报地区id列表
  2. C++ QT中国象棋项目讲解(四) 简单的人机对战
  3. 如何在调用方法时,让方法中的参数指向元素本身
  4. 使用UnrealPak.exe创建Pak文件
  5. 方舟の女:再论黑洞宇宙霍金熵,信息论,测不准原理和普朗克常数
  6. 小米6设置位置服务器,小米6手机这样设置最科学
  7. 计算机职称照图片,职称计算机xp系统知识:插入图片、艺术字、图示
  8. Latex 图片及表格排列代码
  9. 现在的亚马逊收款账户怎么开?容易开吗?有谁了解过?
  10. audition cc变声插件_Adobe Audition CC怎么安装插件?