1. 程式人生 > >51nod 1272 思維/線段樹

51nod 1272 思維/線段樹

can mes ima color 循環 code bit str 51nod

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1272

1272 最大距離技術分享

題目來源: Codility 基準時間限制:1 秒 空間限制:131072 KB 分值: 20 難度:3級算法題 技術分享 收藏 技術分享 關註 給出一個長度為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
輸出最大距離。
Input示例
6
5
3
6
3
4
2
Output示例
3
一個很明顯的做法是線段樹維護區間最大值,然後二分查找最右的點。
我們還可以將這些數標記坐標之後按照值得大小升序排列,價值相同的坐標小的優先。
排序之後,每個數的最優點一定位於這個數的右側,換句話說將求解的問題看做一個區間,我們固定右端點之後只要找到一個下標最小的左端點就好了,
遍歷這些數據順便維護一個最小的左端點,當前標記大於這個最小值就更新答案,小於的話說明這個數找不到與他匹配的,更新最小標記。
固定右端點找id最小的左端點,顯然我們不必要每次都重新找,只要從左至右循環順便維護一下這個最小值就好了。
 1
//排序做法 2 #include<bits/stdc++.h> 3 using namespace std; 4 struct node 5 { 6 int val,id; 7 bool operator<(const node &tmp)const{ 8 if(val!=tmp.val) return val<tmp.val; 9 return id<tmp.id; 10 } 11 }P[50005]; 12 int main() 13 { 14 int N,i,j,k,maxd=0; 15 scanf("
%d",&N); 16 for(i=1;i<=N;++i) 17 { 18 scanf("%d",&P[i].val); 19 P[i].id=i; 20 }sort(P+1,P+1+N); 21 int mini=P[1].id; 22 for(i=1;i<=N;++i) 23 { 24 if(P[i].id<mini) mini=P[i].id; 25 else maxd=max(maxd,P[i].id-mini); 26 } 27 printf("%d\n",maxd); 28 return 0; 29 } 30 31 //ST做法 32 #include<bits/stdc++.h> 33 using namespace std; 34 struct SegTree 35 { 36 #define M ((L+R)>>1) 37 #define lc (id<<1) 38 #define rc (id<<1|1) 39 int maxv[50005<<2],A[50005],tot; 40 void init(){memset(maxv,0,sizeof(maxv));tot=0;} 41 void build(int L,int R,int id) 42 { 43 if(L==R){scanf("%d",&maxv[id]);A[++tot]=maxv[id];return;} 44 build(L,M,lc); 45 build(M+1,R,rc); 46 maxv[id]=max(maxv[lc],maxv[rc]); 47 } 48 int Find(int L,int R,int id,int v) 49 { 50 if(L==R) return L; 51 if(maxv[rc]>=v) return Find(M+1,R,rc,v); 52 else return Find(L,M,lc,v); 53 } 54 }seg; 55 int main() 56 { 57 int N,i,j,k,maxd=0; 58 scanf("%d",&N); 59 seg.init(); 60 seg.build(1,N,1); 61 for(i=1;i<=N;++i) 62 { 63 maxd=max(maxd,seg.Find(1,N,1,seg.A[i])-i); 64 } 65 printf("%d\n",maxd); 66 return 0; 67 }

51nod 1272 思維/線段樹