• 拦截导弹


    题目描述

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

    输入导弹依次飞来的高度(雷达给出的高度数据是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);
    }
    
  • 相关阅读:
    参加过的面试题目总结
    小论文实验讨论——不同的分类算法
    【设计模式】行为型07备忘录模式(Memento Pattern)
    【设计模式】行为型06命令模式(Command Pattern)
    【设计模式】行为型05责任链模式(Chain of responsibility Pattern)
    【设计模式】行为型04迭代器模式(Iterator Pattern)
    【设计模式】行为型03观察者模式(Observer Pattern)
    【设计模式】行为型02模板方法模式(Template Method Patten)
    【JVM】02垃圾回收机制
    【死磕线程】线程同步机制_java多线程之线程锁
  • 原文地址:https://www.cnblogs.com/ZUTTER/p/9726502.html
Copyright © 2020-2023  润新知