zoukankan      html  css  js  c++  java
  • 【BZOJ1049】 [HAOI2006]数字序列

    BZOJ1049 [HAOI2006]数字序列


    dp好题?

    第一问

    第一问我会做!令(b_i=a_i-i),求一个最长不下降子序列.

    (n-ans)就是最终的答案.

    第二问

    好难啊.不会.挖坑待补.

    考虑一下对于一个ij的可能符合情况,定然存在一个$k$在ik之中为(a_i),k~j之中为(a_j).

    然后就可以dp了.

    这个转移比较玄学.如果不随机就GG了.

    随机的证明

    代码实现

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<iostream>
    using namespace std;
    #define ll long long
    #define re register
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    inline int gi()
    {
    	int f=1,sum=0;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    	return f*sum;
    }
    const int N=50010;
    int a[N],n,L,cnt,mn[N],f[N],front[N],to[N<<2],nxt[N<<2];
    ll g[N],s1[N],s2[N];
    int find(int x){
    	int l=1,r=L,t=0;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(mn[mid]<=x)t=mid,l=mid+1;
    		else r=mid-1;
    	}
    	return t;
    }
    void dp(){
    	memset(mn,127,sizeof(mn));
    	mn[0]=-(1<<30);
    	for(int i=1;i<=n;i++){
    		int q=find(a[i]);
    		f[i]=q+1;
    		L=max(L,f[i]);
    		mn[q+1]=min(mn[q+1],a[i]);
    	}
    }
    void Add(int u,int v){
    	to[++cnt]=v;nxt[cnt]=front[u];front[u]=cnt;
    }
    void solve(){
    	for(int i=n;~i;i--){
    		Add(f[i],i);
    		g[i]=1ll<<60;
    	}
    	g[0]=0;a[0]=-(1<<30);
    	for(int u=1;u<=n;u++)
    		for(int i=front[f[u]-1];i;i=nxt[i]){
    			int v=to[i];
    			if(v>u)break;
    			if(a[v]>a[u])continue;
    			for(int j=v;j<=u;j++)s1[j]=abs(a[v]-a[j]),s2[j]=abs(a[u]-a[j]);
    			for(int j=v+1;j<=u;j++)
    				s1[j]+=s1[j-1],s2[j]+=s2[j-1];
    			for(int j=v;j<u;j++)
    				g[u]=min(g[u],g[v]+s1[j]-s1[v]+s2[u]-s2[j]);
    		}
    }
    int main(){
    	n=gi();
    	for(int i=1;i<=n;i++)a[i]=gi()-i;
    	a[++n]=1<<30;
    	dp();solve();
    	printf("%d
    %lld
    ",n-f[n],g[n]);
    	return 0;
    }
    
  • 相关阅读:
    [转]只有tcp6没有tcp问题
    Makefile 中:= ?= += =的区别
    【转】docker images 介绍
    [转]我眼中的 Docker(二)Image
    【转】一个简单的Dockerfile实例
    【转】Prometheus 介绍
    [转]MySQL索引类型按存储类型和逻辑区分
    【转】mysql索引类型
    用Unity制作游戏,你需要深入了解一下IL2CPP
    c++中CreateEvent函数
  • 原文地址:https://www.cnblogs.com/mleautomaton/p/10314664.html
Copyright © 2011-2022 走看看