zoukankan      html  css  js  c++  java
  • nyoj 119士兵杀敌(三)(线段树区间最值查询,RMQ算法)

    士兵杀敌(三)

    时间限制:2000 ms  |  内存限制:65535 KB
    难度:5
    描写叙述

    南将军统率着N个士兵,士兵分别编号为1~N,南将军常常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比較,计算出两个人的杀敌数差值。用这样的方法一方面能鼓励杀敌数高的人,还有一方面也算是批评杀敌数低的人,起到了非常好的效果。

    所以,南将军常常问军师小工第i号士兵到第j号士兵中,杀敌数最高的人与杀敌数最低的人之间军功差值是多少。

    如今,请你写一个程序,帮小工回答南将军每次的询问吧。

    注意,南将军可能询问非常多次。

    输入
    仅仅有一组測试数据
    第一行是两个整数N,Q。当中N表示士兵的总数。Q表示南将军询问的次数。

    (1<N<=100000,1<Q<=1000000)
    随后的一行有N个整数Vi(0<=Vi<100000000)。分别表示每一个人的杀敌数。


    再之后的Q行。每行有两个正正数m,n。表示南将军询问的是第m号士兵到第n号士兵。

    输出
    对于每次询问。输出第m号士兵到第n号士兵之间全部士兵杀敌数的最大值与最小值的差。
    例子输入
    5 2
    1 2 6 9 3
    1 2
    2 4
    例子输出
    1
    7
    来源
    经典改编
    上传者
    张云聪


    看到这种题就想到线段树 唉 还是知道的算法太少了

    第一次线段树还超时了(粗心 忘记写return 了)

    还能够用RMQ算法(比线段树快多了。。)  。百度的。

    。。

    线段树 1836ms 险过。

    。。

     
    #include <stdio.h>
    #include <algorithm>
    using namespace std;
    struct node
    {
    	int left,right;
    	int max_num,min_num;
    }tree[100000*4];
    void build(int left,int right,int root)
    {
    	tree[root].left=left;
    	tree[root].right=right;
    	if(left==right)
    	{
    		scanf("%d",&tree[root].max_num);
    		tree[root].min_num=tree[root].max_num;
    		return ;
    	}
    	else
    	{
    		int mid=(left+right)/2;
    		build(left,mid,root*2);
    		build(mid+1,right,root*2+1);
    		tree[root].max_num=max(tree[root*2].max_num,tree[root*2+1].max_num);
    		tree[root].min_num=min(tree[root*2].min_num,tree[root*2+1].min_num);
    	}
    }
    void search(int l,int r,int root,int &c,int &d)
    {
    	if(tree[root].left==l&&tree[root].right==r)
    	{
    		c=tree[root].max_num;
    		d=tree[root].min_num;
    		return ;
    	}
    	int mid=(tree[root].left+tree[root].right)/2;
    	if(mid>=r)
    	search(l,r,root*2,c,d);
    	else if(mid<l)
    	search(l,r,root*2+1,c,d);
    	else
    	{
    		int c1,d1;
    		search(l,mid,root*2,c,d);
    		search(mid+1,r,root*2+1,c1,d1);
    		c=max(c,c1);
    		d=min(d,d1);
    	}
    }
    int main()
    {
    	int n,k;
    	scanf("%d %d",&n,&k);
    	build(1,n,1);
    	for(int i=0;i<k;i++)
    	{
    		int a,b;
    		int c,d;
    		scanf("%d %d",&a,&b);
    		search(a,b,1,c,d);
    		printf("%d
    ",c-d);
    	}
    }        

    RMQ算法 976ms 节省了近一倍的事件。

    假设不懂RMQ (Range Minimum/Maximum Query)算法 

    点击打开链接我转载的小牛一篇文章

    #include <stdio.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    int min_num[100005][20];
    int max_num[100005][20];
    int n,k;
    void RMQ()
    {
    	for(int i=1;i<20;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			if(j+(1<<i)-1<=n)
    			{
    				max_num[j][i]=max(max_num[j][i-1],max_num[j+(1<<(i-1))][i-1]);
    				min_num[j][i]=min(min_num[j][i-1],min_num[j+(1<<(i-1))][i-1]);
    			}
    		}
    	}
    	
    }
    int main()
    {
    	scanf("%d %d",&n,&k);
    	for(int i=1;i<=n;i++)
    	{
    		int x;
    		scanf("%d",&x);
    		min_num[i][0]=max_num[i][0]=x;
    	}
    	RMQ();
    	for(int i=0;i<k;i++)
    	{
    		int a,b;
    		scanf("%d %d",&a,&b);
    		int pos=(int)(log(b-a+1.0)/log(2.0));
    		int max1=max(max_num[a][pos],max_num[b-(1<<pos)+1][pos]);
    		int min1=min(min_num[a][pos],min_num[b-(1<<pos)+1][pos]);
    		printf("%d
    ",max1-min1);
    	}
    	return 0;
    }



  • 相关阅读:
    Spring 中PageHelper分页插件使用
    手写Spring框架学习笔记
    Spring 集成Junit单元测试
    创建产品服务工程
    Oracle 常用SQL语句
    解决The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone
    微服务如何拆分
    Eureka的高可用
    Eureka Client的使用
    Spring Cloud Eureka Server使用(注册中心)
  • 原文地址:https://www.cnblogs.com/yfceshi/p/7391013.html
Copyright © 2011-2022 走看看