zoukankan      html  css  js  c++  java
  • CF474E Pillars(离散化+线段树+保存DP路径)

    题意:

    给出一个序列,一次跳跃只能从i跳到j,满足j>i同时abs(a[j]-a[i])>=d。询问最多可以跳几次,输出路径。

    题解:

    做过很多次的DP模型,需要注意的是这里的值域是1e15,需要先对数据做一个离散化,然后二分出每步DP的上下界。保存DP路径的细节在线段树和状态转移的过程中都有体现,属于常见套路!

    /*
     *author: zlc
     *zucc_acm_lab
     *just do it
     */
    #include<bits/stdc++.h> 
    using namespace std;
    typedef long long ll;
    const double pi=acos(-1.0);
    const double eps=1e-6;
    const int mod=1e9+7;
    const int inf=1e9;
    const int maxn=2e5+100;
    inline ll read () {ll x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
    ll qpow (ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
    ll n,d;
    ll a[maxn];
    ll t[maxn];
    ll dp[maxn];
    ll pre[maxn];
    
    struct node {
        int l,r;
        pair<ll,ll> sum;
    }segTree[maxn<<2];
    void build (int i,int l,int r) {
        segTree[i].l=l;
        segTree[i].r=r;
        segTree[i].sum.first=-1;
        segTree[i].sum.second=-1;
        if (l==r) {
            return;
        }
        int mid=(l+r)>>1;
        build(i<<1,l,mid);
        build(i<<1|1,mid+1,r);
        segTree[i].sum=max(segTree[i<<1].sum,segTree[i<<1|1].sum);
    }
    void up (int i,ll p,ll v,ll pre) {
        if (segTree[i].l==p&&segTree[i].r==p) {
            segTree[i].sum=max(segTree[i].sum,make_pair(v,pre));
            return;
        }
        ll mid=(segTree[i].l+segTree[i].r)>>1;
        if (p<=mid)
            up(i<<1,p,v,pre);
        if (p>mid)
            up(i<<1|1,p,v,pre);
        segTree[i].sum=max(segTree[i<<1].sum,segTree[i<<1|1].sum);
    }
    pair<ll,ll> query (int i,int l,int r) {
        if (l>r) return make_pair(-1ll,-1ll);
        if (segTree[i].l>=l&&segTree[i].r<=r) 
            return segTree[i].sum;
        int mid=(segTree[i].l+segTree[i].r)>>1;
        pair<ll,ll> ans=make_pair(0ll,0ll);
        if (l<=mid)
            ans=max(ans,query(i<<1,l,r));
        if (r>mid)
            ans=max(ans,query(i<<1|1,l,r));
        return ans;    
    }
    int main () {
        n=read(),d=read();
        for (int i=1;i<=n;i++) a[i]=read(),t[i]=a[i];
        sort(t+1,t+n+1);
        int m=unique(t+1,t+n+1)-t-1;
        for (int i=1;i<=n;i++) a[i]=upper_bound(t+1,t+m+1,a[i])-t-1;
        //for (int i=1;i<=n;i++) printf("%lld ",a[i]);printf("
    "); 
        build(1,1,m+1);
        for (int i=1;i<=n;i++) {
            int Min=upper_bound(t+1,t+m+1,t[a[i]]-d)-t;
            int Max=lower_bound(t+1,t+m+1,t[a[i]]+d)-t;
            Min--;
            pair<ll,ll> t1=query(1,1,Min);
            if (t1.first+1>dp[i]) {
                dp[i]=t1.first+1;
                pre[i]=t1.second;
            }
            pair<ll,ll> t2=query(1,Max,m);
            if (t2.first+1>dp[i]) {
                dp[i]=t2.first+1;
                pre[i]=t2.second;
            }
            up(1,a[i],dp[i],i);
        }
        ll ans=0,u=-1;
        for (int i=1;i<=n;i++) {
            if (dp[i]>ans) {
                ans=dp[i];
                u=i;
            }
        }
        printf("%lld
    ",ans);
        vector<int> wjm;
        while (u) {
            wjm.push_back(u);
            u=pre[u];
        }
        reverse(wjm.begin(),wjm.end());
        for (int v:wjm) printf("%d ",v);
        printf("
    ");
        
    }
  • 相关阅读:
    weblogic复现利用系列-2019
    weblogic复现利用系列-2020
    Python3编码解码与数据类型转换
    weblogic复现利用系列-2017
    weblogic从ssrf到redis获取shell
    fastjson反序列化复现
    shiro721复现
    Shiro550复现和挖掘思路
    RMI反序列化
    手写一个admin 组件------STARK
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13661896.html
Copyright © 2011-2022 走看看