Codeforces Round #271 (Div. 2) E 离散化+线段树

来源:互联网 发布:淘宝刷心悦会员安全吗 编辑:程序博客网 时间:2024/06/06 01:09



链接:戳这里


E. Pillars
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Marmot found a row with n pillars. The i-th pillar has the height of hi meters. Starting from one pillar i1, Marmot wants to jump on the pillars i2, ..., ik. (1 ≤ i1 < i2 < ... < ik ≤ n). From a pillar i Marmot can jump on a pillar j only if i < j and |hi - hj| ≥ d, where |x| is the absolute value of the number x.

Now Marmot is asking you find out a jump sequence with maximal length and print it.

Input
The first line contains two integers n and d (1 ≤ n ≤ 105, 0 ≤ d ≤ 109).

The second line contains n numbers h1, h2, ..., hn (1 ≤ hi ≤ 1015).

Output
The first line should contain one integer k, the maximal length of a jump sequence.

The second line should contain k integers i1, i2, ..., ik (1 ≤ i1 < i2 < ... < ik ≤ n), representing the pillars' indices from the maximal length jump sequence.

If there is more than one maximal length jump sequence, print any.

Examples
input
5 2
1 3 6 7 4
output
4
1 2 3 5 
input
10 3
2 1 3 6 9 11 7 3 20 18
output
6
1 4 6 7 8 9 
Note
In the first example Marmot chooses the pillars 1, 2, 3, 5 with the heights 1, 3, 6, 4. Another jump sequence of length 4 is 1, 2, 4, 5.


题意:

有n根柱子,每根柱子高度为hi。人当前在第j根柱子,可以跳到前面的任意第i根柱子,只需要满足|aj-ai|>=d

问最多能跳多少根柱子。输出答案,并输出答案跳的路径


思路:

很容易想到dp[i]:表示当前第i根柱子的最优值

那么dp[i]肯定是从前面的dp[1~j] (1<=j<i)的最优值里面继承过来,类于LIS的On*n思想,但是这样会T

考虑我们需要快速找出(1~j)中的满足,aj-ai>=d || ai-aj>=d 的最大值dp[j],发现是找出两个区间的最大值

线段树下标从小到大存柱子的高度顺序(注意是高度大小顺序),由于高度太大,这里需要离散化一下。

线段树存两个权值,分别是当前区间的最大值dp[l,r]以及当前区间最大值所在的原hi数组的下标,方便记录路径


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include <ctime>#include<queue>#include<set>#include<map>#include<stack>#include<iomanip>#include<cmath>#include<bitset>#define mst(ss,b) memset((ss),(b),sizeof(ss))///#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;#define INF (1ll<<60)-1#define Max 1e9using namespace std;int n;ll d;ll a[100100],b[100100];int dp[100100],pre[100100];int tr[400100],id[400100];void build(int root,int l,int r){    if(l==r) {        tr[root]=0;        return ;    }    int mid=(l+r)/2;    build(root*2,l,mid);    build(root*2+1,mid+1,r);}pair<int,int> query(int root,int l,int r,int x,int y){    if(x<=l &&y>=r){        return make_pair(tr[root],id[root]);    }    int mid=(l+r)/2;    pair<int,int> ans;    ans=make_pair(0,0);    if(x<=mid){        pair<int,int> tmp=query(root*2,l,mid,x,y);        if(ans.first<tmp.first){            ans=tmp;        }    }    if(y>mid){        pair<int,int> tmp=query(root*2+1,mid+1,r,x,y);        if(ans.first<tmp.first){            ans=tmp;        }    }     if(tr[root*2]>=tr[root*2+1]){        tr[root]=tr[root*2];        id[root]=id[root*2];    } else {        tr[root]=tr[root*2+1];        id[root]=id[root*2+1];    }    return ans;}void update(int root,int l,int r,int pos,int i,int v){    if(l==pos && r==pos){        if(tr[root]<v){            tr[root]=v;            id[root]=i;        }        return ;    }    int mid=(l+r)/2;    if(pos<=mid){        update(root*2,l,mid,pos,i,v);    } else if(pos>mid) update(root*2+1,mid+1,r,pos,i,v);    if(tr[root*2]>=tr[root*2+1]){        tr[root]=tr[root*2];        id[root]=id[root*2];    } else {        tr[root]=tr[root*2+1];        id[root]=id[root*2+1];    }}void print(int x){    if(x==0) return ;    else print(pre[x]);    printf("%d ",x);}int main(){    scanf("%d%I64d",&n,&d);    for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);    for(int i=1;i<=n;i++) b[i]=a[i];    sort(b+1,b+n+1);    int m=unique(b+1,b+n+1)-(b+1);    build(1,1,m);    int ans=0,root=-1;    for(int i=1;i<=n;i++){        dp[i]=0;        int L=upper_bound(b+1,b+m+1,a[i]-d)-b;        int R=lower_bound(b+1,b+m+1,a[i]+d)-b;        L--;        if(L>=1){            pair<int ,int> p=query(1,1,m,1,L);            if(p.first+1>dp[i]){                dp[i]=p.first+1;                pre[i]=p.second;            }        }        if(R<=m){            pair<int,int> p=query(1,1,m,R,m);            if(p.first+1>dp[i]){                dp[i]=p.first+1;                pre[i]=p.second;            }        }        int x=lower_bound(b+1,b+m+1,a[i])-b;        update(1,1,m,x,i,dp[i]);        if(ans<dp[i]){            ans=dp[i];            root=i;        }    }    printf("%d\n",ans);    if(ans==0) return 0;    print(root);    return 0;}



0 0
原创粉丝点击