Codeforces Round #271 (Div. 2) E Pillars(dp+线段树优化)

来源:互联网 发布:网络推广框架协议 编辑:程序博客网 时间:2024/05/17 03:52

题目要求abs(d[i]-d[j])>=d,也就是说只要a[j]<=a[i]-d或者a[i]+d<=a[j] ,也就是只要求1~a[i]-d即a[i]+d~max里最大的dp值,这就是一个线段树查询问题。建议先看一下本博客里面LIS线段树优化的文章。

下面是AC代码:

  

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define LL long longusing namespace std;int dp[100005],pre[100005];LL s[100005],a[100005];int b[100005];struct pi{    int le;    int ri;    int ma;}pp[400005];void init(int tot,int l,int r){    pp[tot].ma=-1;    pp[tot].le=l;    pp[tot].ri=r;    if(l==r) return ;    init(2*tot,l,(l+r)/2);    init(2*tot+1,(l+r)/2+1,r);}void merg(int tot,int p,int n){    if(pp[tot].le==pp[tot].ri){        if(pp[tot].ma==-1) pp[tot].ma=n;        else{            if(dp[pp[tot].ma]<dp[n]){                pp[tot].ma=n;            }        }        return ;    }    int mid=(pp[tot].le+pp[tot].ri)/2;    if(p<=mid) merg(2*tot,p,n);    else merg(2*tot+1,p,n);    if(pp[2*tot].ma==-1) pp[tot].ma=pp[2*tot+1].ma;    if(pp[2*tot+1].ma==-1) pp[tot].ma=pp[2*tot].ma;    if(dp[pp[2*tot].ma]<dp[pp[2*tot+1].ma]) pp[tot].ma=pp[2*tot+1].ma;    else pp[tot].ma=pp[2*tot].ma;}int query(int tot,int l,int r){    int x,y;    if(l<=pp[tot].le&&r>=pp[tot].ri) return pp[tot].ma;    int mid;    mid=(pp[tot].le+pp[tot].ri)/2;    x=-1;    y=-1;    if(l<=mid) x=query(2*tot,l,r);    if(r>mid) y=query(2*tot+1,l,r);    if(x==-1) return y;    if(y==-1) return x;    if(dp[x]<dp[y]) return y;    return x;}int get(int n,LL k){    int le,ri,mid;    le=1;    ri=n;    while(le<=ri){        mid=(le+ri)/2;        if(s[mid]<k) le=mid+1;        else ri=mid-1;    }    return le;}int main(){    int i,j,n,m,p,k,d,x,y;    LL a1,b1;    cin>>n>>d;    for(i=1;i<=n;i++){        cin>>a[i];        s[i]=a[i];    }    sort(s+1,s+1+n);    dp[0]=0;    init(1,1,n);    memset(pre,-1,sizeof(pre));    for(i=1;i<=n;i++){        if(i==1){            dp[1]=1;            p=get(n,a[i]);            merg(1,p,1);        }        else{            x=-1;            y=-1;            a1=a[i]-d;            if(a1>0){                p=get(n,a1);                if(p>n||s[p]!=a1) p--;            }            else p=0;            if(p>0)            x=query(1,1,p);            b1=a[i]+d;            p=get(n,b1);            if(p<=n) y=query(1,p,n);            if(x==-1&&y==-1) dp[i]=1;            else{                if(x==-1){                    dp[i]=dp[y]+1;                    pre[i]=y;                }                else if(y==-1){                    dp[i]=dp[x]+1;                    pre[i]=x;                }                else{                    if(dp[x]<dp[y]){                        dp[i]=dp[y]+1;                        pre[i]=y;                    }                    else {                        dp[i]=dp[x]+1;                        pre[i]=x;                    }                }            }            p=get(n,a[i]);            merg(1,p,i);        }    }    p=0;    for(i=1;i<=n;i++){        if(dp[i]>p) p=dp[i];    }    int tot;    printf("%d\n",p);    tot=0;    for(i=1;i<=n;i++){        if(dp[i]==p){            b[tot++]=i;            i=pre[i];            while(i!=-1){                b[tot++]=i;                i=pre[i];            }            break;        }    }    for(i=tot-1;i>=0;i--) printf(" %d",b[i]);    printf("\n");}

0 0
原创粉丝点击