zoukankan      html  css  js  c++  java
  • #46 delete(动态规划+树状数组)

      二维的dp非常显然,但这也没有什么优化的余地了。

      注意到最后的方案中只有产生贡献的位置是有用的,剩下的部分可以在该范围内任意选取。

      所以我们考虑设f[i]为i号位最后产生贡献的答案,则f[i]=max{f[j]+1} (i-j>=a[i]-a[j],a[i]>a[j])。

      观察这个限制,即为i-a[i]>=j-a[j]且a[i]>a[j],以及i>j。可以发现这里i>j的限制是可以被前两个限制所包含的。于是我们考虑换个顺序dp,按照a[i]从小到大来。树状数组维护即可。

      至于删数数量,只需要保证i-a[i]<=k<=n-a[i]。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 1000010
    int n,m,tree[N];
    struct data
    {
        int i,x,ans;
        bool operator <(const data&a) const
        {
            return x<a.x;
        }
    }a[N];
    void ins(int k,int x){while (k<=n) tree[k]=max(tree[k],x),k+=k&-k;}
    int query(int k){int s=0;while (k) s=max(tree[k],s),k-=k&-k;return s;}
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("b.in","r",stdin);
        freopen("b.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++)
        a[i].x=read(),a[i].i=i,a[i].ans=-N;
        sort(a+1,a+n+1);
        memset(tree,200,sizeof(tree));
        ins(1,0);
        for (int i=1;i<=n&&a[i].x<=n;)
        {
            int t=i-1;
            while (t<n&&a[t+1].x==a[i].x)
            {
                t++;
                if (a[t].i>=a[t].x) a[t].ans=query(a[t].i-a[t].x+1)+1;
            }
            while (i<=t)
            {
                if (a[i].i>=a[i].x) ins(a[i].i-a[i].x+1,a[i].ans);
                i++;
            }
        }
        for (int i=1;i<=n;i++)
        if (a[i].i-a[i].x<=m&&m<=n-a[i].x) a[0].ans=max(a[0].ans,a[i].ans);
        cout<<a[0].ans;
        return 0;
    }
  • 相关阅读:
    Python 处理时间的模块
    C# 委托在线程与UI界面之间的应用
    C# 自己动手实现Spy++(二)
    C# 自己动手实现Spy++(一)
    VS2008自定义快捷键设置
    C#深入解析委托——C#中为什么要引入委托
    C# 线程 在 sleep,suspend 之后 Abort 的方法
    C#多线程学习笔记之(abort与join配合使用)
    使用命名管道的OVERLAPPED方式实现非阻塞模式编程 .
    C++和C#进程之间通过命名管道通信(上)
  • 原文地址:https://www.cnblogs.com/Gloid/p/9690434.html
Copyright © 2011-2022 走看看