您的位置:首页 > 运维架构

bzoj 4582: [Usaco2016 Open]Diamond Collector (单调队列+线段树)

2016-11-16 14:24 633 查看

4582: [Usaco2016 Open]Diamond Collector

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 119  Solved: 82

[Submit][Status][Discuss]

Description

Bessie the cow, always a fan of shiny objects, has taken up a hobby of mining diamonds in her spare 
time! She has collected N diamonds (N≤50,000) of varying sizes, and she wants to arrange some of th
em in a pair of display cases in the barn.Since Bessie wants the diamonds in each of the two cases t
o be relatively similar in size, she decides that she will not include two diamonds in the same case
 if their sizes differ by more than K (two diamonds can be displayed together in the same case if th
eir sizes differ by exactly K). Given K, please help Bessie determine the maximum number of diamonds
 she can display in both cases together.
给定长度为N的数列a,要求选出两个互不相交的子序列(可以不连续),满足同一个子序列中任意两个元素差的绝
对值不超过K。最大化两个子序列长度的和并输出这个值。1 ≤ N ≤ 50000, 1 ≤ a_i ≤ 10 ^ 9, 0 ≤ K ≤ 10^ 9

Input

The first line of the input file contains N and K (0≤K≤1,000,000,000). The next NN lines each cont
ain an integer giving the size of one of the diamonds. All sizes will be positive and will not excee
d 1,000,000,000

Output

Output a single positive integer, telling the maximum number of diamonds that Bessie can showcase in
 total in both the cases.

Sample Input

7 3

10

5

1

12

9

5

14

Sample Output

5

HINT

Source

Silver鸣谢frank_c1提供翻译

[Submit][Status][Discuss]

题解:单调队列+线段树

按权值排序,然后用单调队列处理出从位置i最远可以延伸到的位置。

然后根据长度建立线段树,枚举第一区间的起点,然后线段树查询区间终点后面长度最长的区间。

但是其实还可以做两遍单调队列预处理出每个位置向前最远延伸的长度和向后最远延伸的长度。

l[i]=max(l[i],l[i-1]) 

r[i]=max(r[i],r[i+1])

然后枚举断点即可。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#define N 50003
#define LL long long
using namespace std;
int n,pos
,ans,tr[N*4];
LL val
,m;
int cmp(int x,int y)
{
return x>y;
}
void update(int now)
{
tr[now]=max(tr[now<<1],tr[now<<1|1]);
}
void build(int now,int l,int r)
{
if (l==r) {
tr[now]=pos[l]-l+1;
return;
}
int mid=(l+r)/2;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
update(now);
}
int qjmax(int now,int l,int r,int ll,int rr)
{
if (ll>rr) return 0;
if(ll<=l&&r<=rr) return tr[now];
int mid=(l+r)/2; int ans=0;
if (ll<=mid) ans=max(ans,qjmax(now<<1,l,mid,ll,rr));
if (rr>mid) ans=max(ans,qjmax(now<<1|1,mid+1,r,ll,rr));
return ans;
}
int main()
{
freopen("diamond.in","r",stdin);
freopen("diamond.out","w",stdout);
scanf("%d%I64d",&n,&m);
for (int i=1;i<=n;i++) scanf("%I64d",&val[i]),pos[i]=i;
int l=1; int r=1;
sort(val+1,val+n+1,cmp);
while (l<=n) {
while (val[l]-val[r+1]<=m&&r+1<=n)
r++;
pos[l]=r;
l++;
}
//for (int i=1;i<=n;i++) cout<<pos[i]<<" ";
//cout<<endl;
build(1,1,n);
for (int i=1;i<=n;i++)
ans=max(ans,pos[i]-i+1+qjmax(1,1,n,pos[i]+1,n));
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: