[洛谷] P1020 导弹拦截
时间:2020-04-25
本文章向大家介绍[洛谷] P1020 导弹拦截 ,主要包括[洛谷] P1020 导弹拦截 使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
O(n²)代码:
1 #include <stdio.h> 2 const int MAXN = 100005; 3 int input[MAXN]; 4 int dec[MAXN]; 5 int inc[MAXN]; 6 int cnt = 0; 7 int ans_max = 0; 8 int ans_need = 0; 9 int main() 10 { 11 //读入 12 int tmp; 13 while(scanf("%d",&tmp) != EOF) 14 { 15 input[cnt++] = tmp; 16 } 17 //初始化 18 for(int i = 0;i < MAXN;i++) 19 { 20 dec[i] = 1; 21 inc[i] = 1; 22 } 23 //最长下降子序列 24 for(int i = cnt- 1;i >= 0;i--){ 25 for(int j = i + 1;j < cnt;j++){ 26 if(input[i] >= input[j]){ 27 if(dec[i] < dec[j] + 1) 28 { 29 dec[i] = dec[j] + 1; 30 } 31 } 32 } 33 if(dec[i] > ans_max) 34 ans_max = dec[i]; 35 } 36 printf("%d\n",ans_max); 37 38 39 //最长上升子序列 40 for(int i = 0;i < cnt;i++){ 41 for(int j = i - 1;j >= 0;j--){ 42 if(input[i] > input[j]){ 43 if(inc[i] < inc[j] + 1) 44 inc[i] = inc[j] + 1; 45 } 46 } 47 if(ans_need < inc[i]) 48 ans_need = inc[i]; 49 } 50 printf("%d",ans_need); 51 return 0; 52 }
思路:
第一问:显然求最长不上升子序列长度即可,
第二问:求共能组成几条最长不上升子序列
Dilworth定理:偏序集的最少反链划分数等于最长链的长度(证明略)
就是求最长上升子序列
但是常规dp方法只有n²复杂度,此题只有100分(满分200)
O(nlogn)代码
1 #include <stdio.h> 2 #include <algorithm> 3 using namespace std; 4 const int MAXN = 1000001; 5 int n; 6 int m; 7 int array[MAXN]; 8 int tree[MAXN]; 9 void build(int tree[],int array[],int node,int start,int end) 10 { 11 if(start == end) { 12 13 tree[node] = 0; 14 } 15 else{ 16 17 int mid = (start + end) / 2; 18 int left_node = 2 * node + 1; 19 int right_node = 2 * node + 2; 20 21 build(tree,array,left_node,start,mid); 22 build(tree,array,right_node,mid + 1,end); 23 tree[node] = max(tree[left_node], tree[right_node]); 24 } 25 26 } 27 void update(int tree[],int array[],int node,int start,int end,int idx,int val) 28 { 29 if(start == end){ 30 tree[node] = val; 31 return; 32 } 33 else 34 { 35 int mid = (start + end) / 2; 36 int left_node = 2 * node + 1; 37 int right_node = 2 * node + 2; 38 if(idx >= start && idx <= mid){ 39 update(tree,array,left_node,start,mid,idx,val); 40 } 41 else{ 42 update(tree,array,right_node,mid + 1,end,idx,val); 43 } 44 tree[node] = max(tree[left_node] ,tree[right_node]); 45 } 46 } 47 int query(int array[],int tree[],int node,int start,int end,int L,int R) 48 { 49 if(R < start || L > end){ 50 // printf("start:%d,end:%d L:%d R:%d\n",start,end,L,R); 51 return 0; 52 } 53 else if(start >= L && end <= R) 54 { 55 // printf("start:%d,end:%d L:%d R:%d tree[%d] = %d\n return ",start,end,L,R,node,tree[node]); 56 return tree[node]; 57 } 58 else if(start == end){ 59 // printf("start:%d,end:%d L:%d R:%d tree[%d] = %d\n",start,end,L,R,node,tree[node]); 60 return tree[node]; 61 } 62 else{ 63 // printf("start:%d,end:%d L:%d R:%d tree[%d] = %d\n",start,end,L,R,node,tree[node]); 64 int mid = (start + end) / 2; 65 int left_node = 2 * node + 1; 66 int right_node = 2 * node + 2; 67 int sum_left = query(array,tree,left_node,start,mid,L,R); 68 int sum_right = query(array,tree,right_node,mid + 1,end,L,R); 69 return max(sum_left, sum_right); 70 } 71 72 73 } 74 int ans = 0; 75 int cnt = 0; 76 int max_height = 0; 77 int main() 78 { 79 int tmp; 80 while(scanf("%d",&tmp) != EOF) 81 { 82 array[cnt++] = tmp; 83 if(tmp > max_height) 84 max_height = tmp; 85 86 } 87 build(tree,array,1,1,max_height); 88 for(int i = 0;i < cnt;i++) 89 { 90 int tmp = query(array,tree,1,1,max_height,array[i],max_height)+1; 91 update(tree,array,1,1,max_height,array[i],tmp); 92 if(tmp>ans) ans=tmp; 93 } 94 printf("%d\n",ans); 95 96 ans=0; 97 build(tree,array,1,1,max_height); 98 for(int i = 0;i < cnt;i++) 99 { 100 int tmp=query(array,tree,1,1,max_height,1,array[i] - 1)+1; 101 update(tree,array,1,1,max_height,array[i],tmp); 102 if (tmp>ans) ans=tmp; 103 } 104 printf("%d",ans); 105 return 0; 106 }
思路:
1.重点是将高度值来当作线段树下标,而不是时间序
2.通过线段树来维护区间最长序列长度最大值
反思:线段树处理可以将输入数据离散化,若数据为1,2,200000,则不需要建呢么打树,只需要记录相对大小1,2,3也可得到相应答案
,为什么可以用线段树,一知半解注意透彻理解求LIS的过程。
原文地址:https://www.cnblogs.com/Ponytai1/p/12773477.html
- Tomcat6/7应用服务器-禁用RC4等弱密码套件
- mybaits3整合spring总结
- 如何使用Airgeddon找回WiFi密码
- 设计缺陷将导致亚马逊Echo变身成为监听设备
- Unity引擎与C#脚本简介
- Redis分布式缓存系统Lua脚本食用指引
- 基于复杂方案OWSAP CsrfGuard的CSRF安全解决方案(适配nginx + DWR)
- XMLHttpRequest对象如何兼容各浏览器使用?
- Java使用wsdl生成axis版本webservice服务端/客户端代码
- Java微信支付快速入门&工具类
- redis集群 - linux安装与配置笔记
- Apache RocketMQ 4.0.0 - linux安装与配置笔记
- 数据库连接池-tomcat-jdbc食用笔记
- Java.NIO编程一览笔录
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- python tkiner实现 一个小小的图片翻页功能的示例代码
- 在Pytorch中使用Mask R-CNN进行实例分割操作
- PHP类的自动加载机制实现方法分析
- strpos() 函数判断字符串中是否包含某字符串的方法
- Laravel框架基于ajax和layer.js实现无刷新删除功能示例
- 详解php伪造Referer请求反盗链资源
- Laravel框架基于ajax实现二级联动功能示例
- django haystack实现全文检索的示例代码
- 基于Python下载网络图片方法汇总代码实例
- 基于pytorch中的Sequential用法说明
- pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)
- tp5(thinkPHP5)框架数据库Db增删改查常见操作总结
- PHP基于cookie实现统计在线人数功能示例
- PHP实现对数字分隔加千分号的方法
- PHP验证类的封装与使用方法详解