51nod 1272 思维/线段树

Posted zzq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1272 思维/线段树相关的知识,希望对你有一定的参考价值。

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 思维/线段树的主要内容,如果未能解决你的问题,请参考以下文章

51nod1287(二分/线段树区间最值&单点更新)

51nod 1287 线段树

51nod1287(二分线段树)

51nod 1199 Money out of Thin Air(线段树+树剖分)

[51NOD1272]最大距离(贪心)

51Nod 1571 最近等对(线段树离线查询)