1. 程式人生 > >【51Nod - 1272 】最大距離 (思維,排序sort的空間優化)

【51Nod - 1272 】最大距離 (思維,排序sort的空間優化)

題幹:

給出一個長度為N的整數陣列A,對於每一個數組元素,如果他後面存在大於等於該元素的數,則這兩個數可以組成一對。每個元素和自己也可以組成一對。例如:{5, 3, 6, 3, 4, 2},可以組成11對,如下(數字為下標):

(0,0), (0, 2), (1, 1), (1, 2), (1, 3), (1, 4), (2, 2), (3, 3), (3, 4), (4, 4), (5, 5)。其中(1, 4)是距離最大的一對,距離為3。

Input

第1行:1個數N,表示陣列的長度(2 <= N <= 50000)。 
第2 - N + 1行:每行1個數,對應陣列元素Ai(1 <= Ai <= 10^9)。

Output

輸出最大距離。

Sample Input

6
5
3
6
3
4
2

Sample Output

3

解題報告:

   這題第一反應是線段樹,,但是想想思維題怎麼可能上資料結構呢?所以開始往思維方面想,無非就是結構體存位置,排序,開一個數組存某個數最早(或晚)出現的位置等等方法唄、、、 

   線段樹也不難想,離散化一下之後從頭到尾掃,在離散化後的值那個權值那裡存一下下標,並標記說這個值已經出現過了,即維護每個數字出現的最早時刻,即最小下標,然後掃到下一個數a[i]查詢1~getpos(a[i])查詢區間最小值,維護差的最大值就可以了。getpos是找到a[i]對應的離散化以後的值。

   這題我還想到了可否用set<pair>去維護,線上更新set,這樣滿足了每次查詢的元素出現的先後關係,但是對於值的大小,emmm,不好搞啊。反正51Nod - 1065這題是可以set做的。

   這題看看程式碼就懂了,題目中有兩個要素,元素的先後出現的關係,關係是大於等於。排序的目的就是為了先滿足後者(因為後者最麻煩所以先讓他滿足)(為啥最麻煩呢?因為看前後的話比較一下pos然後維護最小值就可以了,但是對於值的話,無法滿足這個單調性,也就是,不好滿足字首可維護關係,所以我們先排序,排除了這個因素,剩下的就是維護一個pos最小值了。)

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
int n,ans;
struct Node {
	int val,pos;
} node[50000 + 5];
bool cmp(const Node& a,const Node& b) {
	if(a.val!= b.val) return a.val < b.val;
	return a.pos < b.pos;
}
int main() 
{
	cin>>n;
	for(int i = 1; i<=n; i++) {
		scanf("%d",&node[i].val);node[i].pos = i;
	}
	sort(node+1,node+n+1,cmp);
	int curpos = node[1].pos;
	for(int i = 1; i<=n; i++) {
		curpos = min(curpos,node[i].pos);
		ans = max(ans,node[i].pos - curpos); 
	}
	printf("%d\n",ans);
	return 0 ;
}

另:如果要求了空間複雜度,那麼就不能排序解決了,這時候考慮用優先佇列去優化空間。 (很巧妙但是可能只有面試的時候會遇到對空間有特別的要求的)

AC程式碼2:(空間複雜度o(1)的版本)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct Node {
	int val,pos;
	friend bool operator <(Node x,Node y) {
		if(x.val==y.val) return x.pos>y.pos;
		return x.val>y.val;
	}
};
priority_queue<Node> pq;
int n;
int main() {
	cin>>n;
	Node tmp;
	for(int i = 1; i<=n; i++) {
		scanf("%d",&tmp.val);tmp.pos=i;
		pq.push(tmp);
	}
	int cur=n,ans=0;
	while(!pq.empty()) {
		Node now = pq.top();pq.pop();
		if(now.pos<cur)  cur=now.pos;
		ans=max(ans,now.pos-cur);
		
	}
	printf("%d\n",ans);

	return 0;
}