bzoj 4582: [Usaco2016 Open]Diamond Collector (单调队列+线段树)
2016-11-16 14:24
633 查看
4582: [Usaco2016 Open]Diamond Collector
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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 sparetime! 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 contain 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 intotal in both the cases.
Sample Input
7 310
5
1
12
9
5
14
Sample Output
5HINT
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);
}
相关文章推荐
- bzoj[2442][Usaco2011 Open]修剪草坪(单调队列+dp)
- bzoj 2442: [Usaco2011 Open]修剪草坪(单调队列)
- BZOJ 1915: [Usaco2010 Open]奶牛的跳格子游戏 单调队列优化dp
- BZOJ_1915_[Usaco2010 Open]奶牛的跳格子游戏_DP+单调队列
- bzoj3126[Usaco2013 Open]Photo 单调队列优化dp
- 【bzoj2442/Usaco2011 Open】修剪草坪——单调队列优化dp
- bzoj 2442: [Usaco2011 Open]修剪草坪 单调队列优化dp
- 【bzoj2442】【Usaco2011 Open】修剪草坪【dp+单调队列】
- BZOJ 4582: [Usaco2016 Open]Diamond Collector
- [BZOJ4582][Usaco2016 Open]Diamond Collector(二分+st表)
- BZOJ_P2442 [Usaco2011 Open]修剪草坪(单调队列)
- 【BZOJ4582】【Usaco2016 open】Diamond Collector 贪心
- bzoj2442[Usaco2011 Open]修剪草坪 单调队列优化dp
- [BZOJ2442][Usaco2011 Open]修剪草坪 dp+单调队列优化
- 单调队列 bzoj3126 [Usaco2013 Open]Photo
- bzoj 4582: [Usaco2016 Open]Diamond Collector
- [BZOJ 2442][Usaco2011 Open]修剪草坪:单调队列
- BZOJ 2442 [Usaco2011 Open]修剪草坪 DP+单调队列优化
- bzoj 3126: [Usaco2013 Open]Photo (DP+单调队列)
- bzoj 3126: [Usaco2013 Open]Photo——单调队列优化dp