51nod 1272 思维/线段树
Posted zzq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1272 思维/线段树相关的知识,希望对你有一定的参考价值。
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=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 思维/线段树的主要内容,如果未能解决你的问题,请参考以下文章