[BZOJ1049][HAOI2006]数字序列(dp)
来源:互联网 发布:seo自然排名 编辑:程序博客网 时间:2024/05/22 09:40
题目描述
传送门
题目大意:给出一个数列,要将其改变成单调上升序列,求最少需要改变多少个数,和在改变的数最少的情况下,每个数改变的绝对值之和的最小值。
题解
第一问,把所有的数减去标号然后求最长不下降子序列就行了
第二问,g(i)表示改好前i个的最小代价,若f(j)+1=f(i)则可以转移,求[j,i]区间内的修改代价可以暴力,枚举一个端点然后将左边的都修改成j,右边的都修改成i,这一步具体的证明可以参考http://pan.baidu.com/share/link?uk=2651016602&shareid=1490516411 orz ydc
因为数据随机,所以我们可以根据第一问求出的f进行分层,然后只在相邻的两个层内暴力,这样时间远远到达不了
并且需要注意的是,在序列的前后各插入一个数,这样好写一些
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define LL long long#define N 35005int n,LSH,ans1;int a[N],b[N],lsh[N],f[N],C[N],p[N],lef[N],rig[N];LL inf,ans2,g[N];void add(int loc,int val){ for (int i=loc;i<=LSH;i+=i&-i) C[i]=max(C[i],val);}int query(int loc){ int ans=0; for (int i=loc;i>=1;i-=i&-i) ans=max(ans,C[i]); return ans;}int cmp(int a,int b){return f[a]<f[b]||(f[a]==f[b]&&a<b);}LL Abs(LL x){return (x>0)?x:-x;}LL calc(int l,int r){ LL now=0; for (int i=l+1;i<r;++i) now+=Abs(lsh[a[i]]-lsh[a[r]]); LL ans=now; for (int i=l+1;i<r;++i) { now-=Abs(lsh[a[i]]-lsh[a[r]]); now+=Abs(lsh[a[i]]-lsh[a[l]]); ans=min(ans,now); } return ans;}int main(){ scanf("%d",&n);int Min=2147483647,Max=-2147483647; for (int i=1;i<=n;++i) { scanf("%d",&a[i+1]);a[i+1]-=i+1; Min=min(Min,a[i+1]);Max=max(Max,a[i+1]); }a[1]=Min-1,a[n+2]=Max+1;n+=2; for (int i=1;i<=n;++i) lsh[++LSH]=a[i]; sort(lsh+1,lsh+LSH+1);LSH=unique(lsh+1,lsh+LSH+1)-lsh-1; for (int i=1;i<=n;++i) a[i]=lower_bound(lsh+1,lsh+LSH+1,a[i])-lsh; f[1]=1;add(a[1],1);p[1]=1; ans1=1; for (int i=2;i<=n;++i) { f[i]=query(a[i])+1; add(a[i],f[i]);p[i]=i; } printf("%d\n",n-f[n]); memset(g,127,sizeof(g));inf=g[0]; g[1]=0; sort(p+1,p+n+1,cmp); for (int i=1;i<=n;++i) if (f[p[i]]!=f[p[i-1]]) lef[f[p[i]]]=i,rig[f[p[i-1]]]=i-1; rig[f[n]]=n; for (int i=1;i<f[n];++i) { int l=lef[i],r=lef[i+1]; while (l<=rig[i]) { if (f[l]!=inf) { while (r<=rig[i+1]&&p[l]>=p[r]) ++r; if (r>rig[i+1]) break; for (int j=r;j<=rig[i+1];++j) if (a[p[j]]>=a[p[l]]) g[j]=min(g[j],g[l]+calc(p[l],p[j])); } ++l; } } printf("%lld\n",g[n]);}
0 0
- [BZOJ1049][HAOI2006]数字序列(dp)
- bzoj1049 [HAOI2006]数字序列 ( LIS + 区间DP)
- 【bzoj1049】【HAOI2006】【数字序列】【dp+暴力】
- [bzoj1049][HAOI2006]数字序列
- bzoj1049: [HAOI2006]数字序列
- BZOJ1049: [HAOI2006]数字序列
- bzoj1049 [HAOI2006]数字序列
- bzoj1049: [HAOI2006]数字序列
- BZOJ1049 数字序列 [DP]
- bzoj1049 数字序列
- 1049: [HAOI2006]数字序列
- BZOJ 1049: [HAOI2006]数字序列
- 【BZOJ 1049】 [HAOI2006]数字序列
- [bzoj 1049] HAOI2006数字序列
- bzoj 1049 [HAOI2006]数字序列
- BZOJ 1049: [HAOI2006]数字序列
- [bzoj] 1049: [HAOI2006]数字序列
- BZOJ系列1049《[HAOI2006]数字序列》题解
- Android Notification
- Go实战--实现简单的restful api(The way to go)
- 解决nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed(2:No such file or durectory)
- Java面向对象设计模式(八)——代理模式(Proxy)
- Linux Fedora或Ubuntu发行版清除旧的内核
- [BZOJ1049][HAOI2006]数字序列(dp)
- nsq源码阅读 nsqlookupd源码四 lookup_protocol_v1.go
- 学习笔记目录
- oracle查看允许的最大连接数和当前连接数等信息
- LeetCode:Two Sum II
- 分布式服务框架ZooKeeper:四字命令
- Java多线程学习
- Android游戏2048的实现
- redis cluster 与lua的结合使用