zoukankan      html  css  js  c++  java
  • 题解 P1020 【导弹拦截】

    题目

    某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

    输入导弹依次飞来的高度(雷达给出的高度数据是 le 50000≤50000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

    数据范围:

    子问题1:n <= 1000

    子问题2:n <= 100000

    思路:序列DP + 线段树优化DP

    首先第一个问题,其实就是求最长不上升序列。

    我们设计 dp[i] 为从 1 到 i 且其最长不上升序列以 i 为结尾的序列长度。那么我们可以从比当颗导弹高或相等的导弹中更新答案。即为:

    dp[i] = max{dp[v]} + 1 (a[v] >= a[i] && v <= i)
    

    这里时间复杂度为O(n^2)。

    对于第二个问题,我们可以想到,假如我们先用一个拦截设施把所有能打下来的导弹都打下来,剩下的拦截设施重复这个动作,一直到所有导弹被拦截。假设我们得到的是最小划分(题目要求)的k组导弹。那么对于第 i 组导弹中任取,在第 i + 1 必定有一个导弹要比这颗导弹高,如果没有,那么我们完全可以把 i + 1 组合并到第 i 组。所以我们找到一个最长的一个上升子序列,肯定序列中的每个导弹对应组导弹,如果多出的话肯定是多余的,如果少的话,不符合上述的分组。所以我们在找最小划分时,只需要找到一个最长上升子序列长度即可。

    我们重新设计 dp[i] 为从 1 到 i 且其最长上升子序列以 i 为结尾的序列长度。同上,我们可以得到:

    dp[i] = max{dp[v]} + 1 (a[v] < a[i] && v <= i)
    

    时间复杂度也为O(n^2)

    对于优化:(两问通用)

    我们可以发现有一维是用来求 dp[] 中满足条件的最大值。我们可以考虑用线段树来优化。我们以 a[i] (就是高度)为坐标,在线段树中维护 f[i] 的最大值。我们在进行有规律的遍历时,每当更新一次 f[i] 我们就将他在线段树中更新,在寻找最大值时,我们按照大小,在相应区间(比如求最长上升子序列中,我们要从高度小于 a[i] 的 f[v] 中转移,所以我们询问 [1, a[i] - 1] 区间的信息)询问,并进行转移即可。

    时间复杂度为O(nlogn)

    code :

    P.S. 代码中注释掉的是没优化时的部分代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<set>
    #include<queue>
    #include<stack>
    using namespace std;
    #define go(i, j, n, k) for(int i = j; i <= n; i += k)
    #define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
    #define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
    #define mn 100010
    #define inf 1 << 30
    #define ll long long
    #define root 1, 50000, 1
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    #define bson l, r, rt
    inline int read(){
    	int x = 0, f = 1; char ch = getchar();
    	while(ch > '9' || ch < '0') { if(ch == '-') f = -f; ch = getchar(); }
    	while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    	return x * f;
    }
    int minn[mn << 2], maxx[mn << 2];
    inline void update(int rt) {
    	minn[rt] = min(minn[rt << 1], minn[rt << 1 | 1]);
    	maxx[rt] = max(maxx[rt << 1], maxx[rt << 1 | 1]);
    }
    inline void build(int l, int r, int rt) {
    	if(l == r) { minn[rt] = maxx[rt] = 0; return; }
    	int m = (l + r) >> 1; build(lson), build(rson), update(rt);
    }
    inline void modify(int l, int r, int rt, int now, int v) {
    	if(l == r) {
    		minn[rt] = v; maxx[rt] = v;
    		return;
    	}
    	int m = (l + r) >> 1;
    	if(now <= m) modify(lson, now, v);
    	else modify(rson, now, v);
    	update(rt);
    }
    inline int query(int l, int r, int rt, int nowl, int nowr) {
    	if(nowl <= l && r <= nowr) return maxx[rt];
    	int m = (l + r) >> 1;
    	if(nowl <= m) {
    		if(m < nowr) return max(query(lson, nowl, nowr), query(rson, nowl, nowr));
    		else return query(lson, nowl, nowr);
    	} else return query(rson, nowl, nowr);
    }
    int f[mn], a[mn], n, ans1, ans2;
    int main(){
    	while(cin >> a[++n]) ;
    	n--;
    	go(i, 1, n, 1) f[i] = 0;
    	build(root);
    	go(i, 1, n, 1) {
    		int maxx = 0, temp = 0;
    //		go(j, 1, i - 1, 1) {
    //			if(maxx < f[j] && a[i] <= a[j]) {
    //				temp = j;
    //				maxx = f[j];
    //			}
    //		}
    		maxx = query(root, a[i], 50000);
    		f[i] = maxx + 1;
    		modify(root, a[i], f[i]);
    		ans1 = max(f[i], ans1);
    	} 
    	cout << ans1 << "
    ";
    	go(i, 1, n, 1) f[i] = 0; 
    	build(root);
    	go(i, 1, n, 1) {
    		int maxx = 0, temp = 0;
    //		go(j, 1, i - 1, 1) {
    //			if(maxx < f[j] && a[i] > a[j]) {
    //				temp = j;
    //				maxx = f[j];
    //			}
    //		}
    		maxx = query(root, 1, a[i] - 1);
    		f[i] = maxx + 1;
    		modify(root, a[i], f[i]);
    		ans2 = max(f[i], ans2);
    	}
    	cout << ans2 << "
    ";
    	return 0;
    }
    
    
  • 相关阅读:
    Difference between application/xml and text/xml
    [转]ASP.NET MVC URL 路由简介
    js Unicode编码转换
    svn更改用户名
    招商银行开发成功国内业界第一个实用的数据仓库系统
    Response.ContentType 详细列表备忘使用(转载)
    WebClient UploadData UploadFile 用法
    char tchar wchar_t WCHAR LPCTSTR LPCWSTR
    网站测试自动化系统—系统应该有的功能
    网站测试自动化系统—收集测试结果
  • 原文地址:https://www.cnblogs.com/yizimi/p/10367145.html
Copyright © 2011-2022 走看看