首页 > 其他分享 >洛谷P1020

洛谷P1020

时间:2023-03-25 19:55:07浏览次数:50  
标签:洛谷 int res bound P1020 序列 500005 dp

P1020 [NOIP1999 普及组] 导弹拦截

思考

这题很显然是一道DP题,第一问就是求该序列的最长不下降子序列.
先说最长不下降子序列的\(O(n^2)\)的做法.


用\(dp_k\)表示第\(k\)位时最大的最长不下降子序列的长度,
那么我们很容易可以得到:
当\(dp_i<dp_j\)且\(i>j\)时,\(dp_i=max(dp_i,dp_j+1)\),
代码就是:

#include<bits/stdc++.h>
//#define int long long
using namespace std;
int n,res,a[500005],dp[500005];
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	while (cin>>a[++n]) ;  //题目的读入方式,有点恶心
	for (int i=1;i<=n;i++){
		for (int j=i-1;j>=1;j--){
			if (a[j]>a[i]) dp[i]=max(dp[i],dp[j]+1);  //状态转移方程式
		}
	}
	for (int i=1;i<=n;i++) res=max(res,dp[i]);  //查找答案
	cout<<res;
	return 0;
}

当然,这个代码会TLE,至于为什么自己看看数据范围和时间复杂度

这个代码就是\(1\to n\)分别向前找,然后找到之前的最大的最长不下降子序列的长度,

如果自己有能力接上去,那么就更新答案,把自己也接上去.

其实听起来像\(Win7\)自带的蜘蛛纸牌,之前机房里网关了,实在无聊死在玩

就是把自己尽可能加到最长的答案上去.

那么第二个输出的东西我实在不想证明太烦了

要涉及到偏序集Dilworth 定理等等,实在烦.

这是佬的证明.

总之只要知道第二个答案是该序列的最长上升序列就行了.

代码我懒得贴,反正之后还要优化的.

优化

首先,我们要确认两个问题:

  1. 怎么优化?

  2. 凭什么可以这么优化?


Q1:怎么优化?

用普通的方法显然不行,所以我们只能另辟蹊径.

而这条路的指向标就是:lower_boundupper_bound

首先我们需要一个数组\(a\)存储从第\(1\)个到第\(n\)个导弹的高度,

一个数组\(res\)存储最长不上升子序列(当然循环过程中绝对不会是答案咯,不然我干嘛还要写代码),

还有一个变量\(t\)代表结尾位置,

我们需要把\(a\)中的元素全都放到\(res\)中去.

** 如果\(b_i\le res_t\),那么就将\(b_i\)放到\(res_i\)之后;**

** 否则说明\(b_i\)不能接在\(res\)之后,所以我们只能把\(b_i\)放进去.**

怎么放呢?在\(res\)数组中找到第一个小于\(b_i\)的数,然后代替它.

然而最快的找法就是用upper_boundlower_bound,因为前面说过,res内是单调不上升的.

所以,我们可以编出程序:

#include<bits/stdc++.h>
//#define int long long
using namespace std;
int n,res[500005],a[500005],t=1;  //记得t=1
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	while (cin>>a[++n]) ;  //读入
	n--;res[1]=a[1];  //初始化
	for (int i=2;i<=n;i++){
		if (res[t]>=a[i]) res[++t]=a[i];
		else res[upper_bound(res+1,res+t+1,a[i],greater<int>())-res]=a[i];
/*              如果实在强迫症可以写成这样:
                else{
                    int p=upper_bound(res+1,res+t+1,a[i],greater<int>())-res;
                    res[p]=a[i];
                }
                对于大佬,可以写成这样:
                *upper_bound(res+1,res+t+1,a[i],greater<int>())=a[i];
*/
	}
	cout<<t;
	return 0;
}

Q2: 凭什么可以这么优化?

证明


设\(res_p\)为\(res\)数组中第一个小于\(b_i\)的元素.

若\(res_p\)不在末尾,那么res_p在之后都不会被用到,且不影响\(t\)的大小,所以可以直接替换;

若\(res_p\)是在末尾,因为\(res_p<b_i\),所以\(res_p\)之后可以接的元素个数绝对少于\(b_i\)之后可以接的元素个数,为了让答案最大化,所以可以放入\(b_i\).


再回过头看看,发现还有一个问题要解决:
最长上升子序列!
这也很好解决,使用lower_bound就行了,而且还不用改比较器.
代码如下:

CODE

#include<bits/stdc++.h>
//#define int long long
using namespace std;
int n,res[500005],a[500005],t=1,ans[500005],w=1;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	while (cin>>a[++n]) ;
	n--;res[1]=ans[1]=a[1];
	for (int i=2;i<=n;i++){
		if (res[t]>=a[i]) res[++t]=a[i];
		else res[upper_bound(res+1,res+t+1,a[i],greater<int>())-res]=a[i];
		if (ans[w]<a[i]) ans[++w]=a[i];
		else ans[lower_bound(ans+1,ans+w+1,a[i])-ans]=a[i];
	}
	cout<<t<<"\n"<<w;
	return 0;
}

标签:洛谷,int,res,bound,P1020,序列,500005,dp
From: https://www.cnblogs.com/Sity-Hugh/p/17255462.html

相关文章

  • 数组模拟双向列表 洛谷 P1160 队列安排
    题目描述一个学校里老师要将班上N个同学排成一列,同学被编号为1~N,他采取如下的方法:1.先将1号同学安排进队列,这时队列中只有他一个人;2.2~N号同学依次入列,编号为i的同学入列方式......
  • 洛谷 P1967 货车运输
    P1967NOIP2013提高组]货车运输-洛谷|计算机科学教育新生态(luogu.com.cn)这个题目算是lca的稍微拓展吧。主要思考方向应该是很明显的。就是考虑一条路径上权值最......
  • 洛谷 P5979 [PA2014]Druzyny
    简要题意有\(n\)个人,把他们划分成尽可能多的区间,其中第\(i\)个人要求它所在的区间长度大于等于\(c_i\),小于等于\(d_i\),求最多的区间数量以及如此划分的方案数。数......
  • 洛谷P1115 最大子段和
    题目传送门题目描述给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。输入格式第一行是一个整数,表示序列的长度 n。第二行有 n 个整数,第......
  • 洛谷 P3758 [TJOI2017]可乐
    https://www.luogu.com.cn/problem/P3758给定一张图。一个机器人在1号点,每次它可以选择留在原地,沿一条边行走一次,自爆。机器人自爆后无法进行任何操作,求t时间内它所有可......
  • 【洛谷】P4590 [TJOI2018]游园会(dp套dp)
    原题链接题意对于一个长度为\(n\)的仅由\(N,O,I\)组成且不包含字串\(NOI\)的字符串\(S\),其与一个给定的长度为\(K\)的字符串的最长公共子序列为\(LCS\)。求出......
  • 【洛谷】P2150 [NOI2015] 寿司晚宴(状压dp+根号分治)
    原题链接题意有序列\(2,3,4\cdotsn\),对于序列中的每一个数,它可以被放入两个集合中的任意一个,或者不选。最后需要满足两个集合间的数两两互质(集合内部的数不需要满足互......
  • 【洛谷】P5904 [POI2014]HOT-Hotels(长链剖分)
    原题链接题意给出一棵有\(n\)个点的树,求有多少组点\((i,j,k)\)满足\(i,j,k\)两两之间的距离都相等。\((i,j,k)\)与\((i,k,j)\)算作同一组。\(1\len\le10^5\)......
  • 洛谷炸了,这次连日爆都没有了
    很讨厌,什么人攻击这么勤快,禁国外ip还防不了......
  • 【洛谷】P2480 [SDOI2010]古代猪文
    原题链接题意求:\[g^{\sum_{d|n}\binom{n}{d}}\mod999911659\]\(n,g\leq10^9\)。思路:因为\(999911659\)是质数,由欧拉定理的推论,可以得到:\[g^{\sum_{d|n}\bino......