拦截导弹

题目描述

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

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

输入输出格式

输入格式:

11行,若干个整数(个数le 100000≤100000)

输出格式:

22行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出样例

输入样例#1: 复制

389 207 155 300 299 170 158 65

输出样例#1: 复制

6
2


考虑一下200分(n log n)的做法

  • 线段树
    不开O2和(n^2)得分是一样的(... 开了可过
#include<iostream>
#include<cstdio>
#define max(a,b) ((a)<(b)? (b) : (a))
#define update(now,a) a[now]=max(a[now*2],a[now*2+1])
using namespace std;

int i,m,n,j,k,a[400000],b[400001],f[400001],c[400001],g[400001],ans,ans2;

void gai(int now,int l,int r,int z,int w,int *a)
{
	if(l==r) {a[now]=z; return ; }
	int mid=(l+r)>>1;
	if(w<=mid) gai(now*2,l,mid,z,w,a);
	else gai(now*2+1,mid+1,r,z,w,a);
	update(now,a);
}

int search(int now,int l,int r,int z)
{
	if(r<=z) return b[now];
	int mid=(l+r)>>1,ans=0;
	ans=max(ans,search(now*2,l,mid,z));
	if(mid<z) ans=max(ans,search(now*2+1,mid+1,r,z));
	return ans;
}

int find(int now,int l,int r,int z)
{
	if(l>=z) return c[now];
	int mid=(l+r)>>1, ans=0;
	ans=max(ans, find(now*2+1,mid+1,r,z));
	if(mid>=z) ans=max(ans, find(now*2,l,mid,z));
	return ans;
}

int main()
{
	freopen("261.in","r",stdin);
	while(scanf("%d",&a[++n])!=EOF) m=max(m,a[n]);
	n-=1;
	for(int i=1;i<=n;i++)
	{
		f[i]=search(1,0,m,a[i]-1)+1;
		gai(1,0,m,f[i],a[i],b);
		ans=max(ans,f[i]);
		g[i]=find(1,0,m,a[i])+1;
		gai(1,0,m,g[i],a[i],c);
		ans2=max(ans2,g[i]);
	}
	printf("%d
%d",ans2,ans);
}

  • 树状数组
    预计得分200
#include<iostream>
#include<cstdio>
#define max(a,b) ((a)<(b)? (b) : (a))
#define lowbit(x) ((x) &(-x))
using namespace std;

int i,m,n,j,k,a[400000],b[400001],c[400001],g[400001],ans,ans2;

int askl(int x)
{
	int ans=0;
	for(int i=x;i>0;i-=lowbit(i)) ans=max(ans,c[i]);
	return ans; 
}

int askr(int x)
{
	int ans=0;
	for(int i=x;i<=m;i+=lowbit(i)) ans=max(ans,b[i]);
	return ans;
}

void addl(int x,int z)
{
	for(int i=x;i>0;i-=lowbit(i)) b[i]=max(z,b[i]);
}

void addr(int x,int z)
{
	for(int i=x;i<=m;i+=lowbit(i)) c[i]=max(z,c[i]);
}

int main()
{
	while(scanf("%d",&a[++n])!=EOF) m=max(m,a[n]);
	n-=1;
	for(int i=1;i<=n;i++)
	{	
		k=askl(a[i])+1;
		addr(a[i]+1,k);
		ans=max(ans,k);
		k=askr(a[i])+1;
		addl(a[i],k);
		ans2=max(ans2,k);
	}
	printf("%d
%d",ans2,ans);
	fclose(stdin);
}
原文地址:https://www.cnblogs.com/ZUTTER/p/9726502.html