zoukankan      html  css  js  c++  java
  • 洛谷P2501 bzoj1049 [HAOI2006]数字序列

    题目链接

    bzoj
    洛谷

    题解

    第一问:

    假如 (i < j)
    如果 (j)能从(i)转移过来
    显然中间空隙必须足够
    例如:(50) (53) (53) (52)
    就不能留下(50)(52)

    那么可以得到如果(j)能从(i)转移过来
    满足
    (a[j]-a[i] >= j-i)
    (=>) (a[j]-j >= a[i]-i)

    那么可以对于以上数列跑一边最长不下降子序列

    第二问:

    将原序列变为上升序列,就等于将新的序列((b_i = a_i-i))变成不下降序列

    那么对于最长不下降子序列相邻两点 (c_{i-1},c_i)

    显然(b)序列上, 在这两点之间的点不会存在 (c_{i-1}<=x<=c_i)

    可以证明,存在一个(k)点, 使得 在(c_{i-1})(k)点之间的点变成(c_{i-1}),剩下的点变成(c_i)
    代价最小

    枚举(k),算出最小值即可

    注意最长不下降子序列不只有一种,需要对于每一种都做一次

    Code

    #include<bits/stdc++.h>
    #define MAX 35010
    using namespace std;
    inline int read() {
    	register int x=0,t=1;
    	register char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-'){t=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    	return x*t;
    }
    struct Line {
    	int v,next;
    }e[MAX<<2];
    int h[MAX],cnt=1,n,H[MAX],Q[MAX],len;
    inline void Add(int u,int v) {
    	e[cnt]=(Line){v,h[u]};
    	h[u]=cnt++;
    }
    int f[MAX];
    long long g[MAX],sum1[MAX],sum2[MAX];
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)H[i]=read()-i;
    	H[++n]=1<<30;
    	for(int i=1;i<=n;++i) {
    		int l=1,r=len,ans=0;
    		while(l<=r) {
    			int mid=(l+r)>>1;
    			if(Q[mid]>H[i])r=mid-1,ans=mid;
    			else l=mid+1;
    		}
    		if(!ans)ans=++len;
    		Q[f[i]=ans]=H[i];
    	}
    	printf("%d
    ",n-len);
    	for(int i=n;i>=0;--i)
    		g[i]=1e18,Add(f[i],i);
    	g[0]=0;H[0]=-H[n];
    	for(int i=1;i<=n;++i) {
    		for(int E=h[f[i]-1];E;E=e[E].next) {
    			int v=e[E].v;
    			if(v>i)break;
    			if(H[v]>H[i])continue;
    			for(int j=v;j<=i;++j) {
    				sum1[j]=sum1[j-1]+abs(H[j]-H[v]);
    				sum2[j]=sum2[j-1]+abs(H[i]-H[j]);
    			}
    			for(int j=v;j<i;++j)
    				g[i]=min(g[i],g[v]+sum1[j]-sum1[v]+sum2[i]-sum2[j]);
    		}
    	}
    	printf("%lld
    ",g[n]);
    	return 0;
    }
    
  • 相关阅读:
    TCP 登录实现代码
    网络编程步骤 乔老师整理
    网络编程步骤 乔老师整理
    UDP 编程 客服咨询回复
    UDP 编程 客服咨询回复
    利用java在服务器和客服端建立连接,进行通讯(代码实例)
    利用java在服务器和客服端建立连接,进行通讯(代码实例)
    InetAddress 类简介
    InetAddress 类简介
    Mysql并发时经典常见的死锁原因及解决方法
  • 原文地址:https://www.cnblogs.com/zzy2005/p/10143547.html
Copyright © 2011-2022 走看看