zoukankan      html  css  js  c++  java
  • 2017京东面试编程题保卫方案

    2017京东面试编程题 - 保卫方案

    题意:

    就是在一个环形的地方,排列着一堆山,要求有几对山是可以相互观察的对方的。
    相互观察的条件是

    1. 如果相邻,必可以互相观察
    2. 不相邻,但是两者之间没有更高的山,可以互相观察,因为环形的,所以有两个方向,顺时针和逆时针,只要有一个方向可以看到就算可以互相观察。

    思路:

    我一开始用最简单的暴力,向两边暴力枚举,复杂度差不多是O(n^2),不然是超时的。
    看了别人题解发现可以用dp做,复杂度是O(n)。

    思路可以说是比较牛批了:

    • 首先要拆环成链,将山的序列改变,第一座山是最高的山。如果第一座是最高的山,那么对于这个环形来说,是不可能通过穿过第一座山去找到可以相互观察的山了,这样就只用讨论正方向的情况了。

    • 其次是统计对于这个序列的L数组和R数组。表示:

    First hill to the left of the x, which is strictly higher than x.
    First hill to the right of the x, which is strictly higher than x.

    • 生成C数组:

    All hills that are as high as x and are located between x and y.

    • 注意left和right统计两次的情况,比如第二高的山在中间的时候

    ac代码

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<cmath>
    
    using namespace std;
    
    const int maxn = 1e6 + 5;
    int a[maxn], b[maxn], L[maxn], R[maxn], C[maxn];
    int n;
    
    int main()
    {
    	cin >> n;			//输入山的数量
    	int ma = -1, mid = 0;			//用于把a[]转化成最高山在第一位数组b[]的临时变量
    	for (int i = 0; i < n; i++)			//输入a
    	{
    		cin >> a[i];
    		if (a[i] > ma)
    		{
    			ma = a[i];
    			mid = i;
    		}
    	}
    	mid--;
    	for (int j = 1; j <= n; j++)			//将a[]转化成最高的山在第一位的b[],最高的山在b[1]
    	{
    		b[j] = a[(mid + j) % n];
    	}
    	L[1] = 1;			//left数组中设定最高的山,下一个比他高的设为1,即自己
    	for (int i = 2; i <= n; i++)			//生成left数组
    	{
    		L[i] = i - 1;			//设定左边的第一座山就比自己高
    		while (L[i] > 1 && b[L[i]] <= b[i])				//while语句左移直到找到比自己要高的山
    			L[i] = L[L[i]];
    	}
    	for (int i = n; i >= 1; i--)			//生成right,C数组
    	{
    		R[i] = i + 1;			//设定右边第一座山就比自己高,并且设定右边的山默认是最高的,因为和最高的山相邻
    		while (R[i] <= n && b[R[i]] < b[i])				//while语句右移知道找到跟自己相等或者比自己高的山
    			R[i] = R[R[i]];
    		if (R[i] <= n && b[R[i]] == b[i])			//如果跟自己一样高,则C[]++
    		{
    			C[i] = C[R[i]] + 1;
    			R[i] = R[R[i]];
    		}
    	}
    
    	long long ans = 0;				//结果可能很大,用longlong存储
    	for (int i = 2; i <= n; i++)			//不用计算最高的山
    	{
    		ans += C[i] + 2;
    		if (L[i] == 1 && R[i] == n + 1)				//此时就是和最高的山形成pair,重复计算了,所以减1
    		{
    			ans--;
    		}
    	}
    	cout << ans << endl;
        return 0;
    }
    
    
  • 相关阅读:
    协方差矩阵
    VS2010+C#+EmguCV 配置详解
    OpenCv,EmguCv及.net之间的互动(The Interaction of OpenCv, EmguCv AND .net)
    EmguCV学习 与opencv的区别和联系
    redis新手入门,摸不着头脑可以看看<二>
    java常用工具类[待补充]
    redis新手入门,摸不着头脑可以看看<一>
    用java代码发送http请求
    Date和long类型互转
    WEB-INF目录下文件复制的几种方式
  • 原文地址:https://www.cnblogs.com/weedboy/p/7157726.html
Copyright © 2011-2022 走看看