
网址如下:
P1020 [NOIP1999 提高组] 导弹拦截 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
怪,实在是怪
怎么会出现在自家电脑运行时间无限接近于0,在洛谷测试的时候超时的情况
在洛谷的o2优化中,是说我的数组访问越界了
但是看不出来哪里有
测试点1的运行时间:

最下面的,接近于0
在洛谷上的:

代码如下:
#include<stdio.h>
#include<ctype.h>
void scanf_line(void);
int dic(int l, int u, int hi);
int dic_2(int l, int u, int hi);
int dp[100001], f[100001], num[100001], g[100001];
int len, maxn = 1, minn = 1;
int main(void)
{
//输入
scanf_line();
//求最长不递增子序列
f[1] = g[1] = num[1];
for(int i = 2; i <= len; i++)
{
//二分法求fx最逼近hi时的x,更新dp以及f,maxn
//初始时的意外情况
if(f[1] <= num[i]) dp[i] = 1, f[1] = num[i];
else if(f[maxn] >= num[i])dp[i] = ++maxn, f[maxn] = num[i];
//正常情况
else
{
dp[i] = dic(1, maxn, num[i]) + 1;
f[dp[i]] = num[i];
}
//二分法求此时的minn值并更新g
//初始时的意外情况
if(g[1] > num[i]) g[1] = num[i];
else if(g[minn] < num[i]) g[++minn] = num[i];
//正常情况
else g[dic_2(1, minn, num[i])] = num[i];
}
//输出
printf("%d\n%d", maxn, minn);
return 0;
}
void scanf_line(void)
{
int ext = 0;
for(char c; (c = getchar()) != '\n'; )
if(isdigit(c))
ext = ext * 10 + c - '0';
else
num[++len] = ext, ext = 0;
num[++len] = ext;
return;
}
int dic(int l, int u, int hi)
{
if(u - l <= 1) return l;
int mid = (l + u) / 2;
if(f[mid] < hi) return dic(l, mid, hi);
else if(f[mid] > hi) return dic(mid, u, hi);
else return mid;
}
int dic_2(int l, int u, int hi)
{
if(u - l <= 1) return u;
int mid = (l + u) / 2;
if(g[mid] < hi) return dic_2(mid, u, hi);
else if(g[mid] > hi) return dic_2(l, mid, hi);
else return mid;
}
参考的题解:
题解 P1020 【[NOIP1999 普及组] 导弹拦截】 - 古明地觉世界第一! - 洛谷博客 (luogu.com.cn)
于2025/2/22添加:
上次做这题的时候是2024/1/22,一年多了
最近在狂刷dp题,刚好推荐的题目里面有之前这个在洛谷那没过的题,就回来做了一下
以下为AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100010;
int f[maxn]{0x3f3f3f3f}, ans, ans2 = 0;
int q[maxn];
int main(void)
{
int val; memset(q, 0x3f, sizeof(q));
while(~scanf("%d", &val)){
int l = 0, r = ans;
while(l < r){
int mid = (l + r + 1) >> 1;
if(f[mid] >= val) l = mid; else r = mid - 1;
}
f[l + 1] = val; ans = max(ans, l + 1);
//求解第二问
l = 0, r = ans2;
while(l < r){
int mid = (l + r) >> 1;
if(q[mid] >= val) r = mid; else l = mid + 1;
}
q[l] = val; if(l == ans2) ans2++;
}
printf("%d\n%d", ans, ans2);
return 0;
}
回头看过去,发现我的代码的风格变了好多,常用语言也从C变成C++了
唉,时间真快,大学四年过了快一半了
本文讲述了作者在解决洛谷竞赛P1020导弹拦截问题时遇到的超时问题,涉及二分法求解最长不递增子序列的代码实现,并对数组访问优化进行分析。

2419

被折叠的 条评论
为什么被折叠?



