bzoj 1049: [HAOI2006]数字序列【dp+二分+瞎搞】
2018-09-28 20:02
323 查看
第一问明显就是用b[i]=a[i]-i来做最长不下降子序列
然后第二问,对于一对f[i]=f[j]+1的(i,j),中间的数一定要改的,并且是等于b[i]或者b[j],我不会证,然后因为是随机数据,所以直接枚举断点用前缀和更新答案即可
证明见http://ydcydcy1.blog.163.com/blog/static/216089040201392851210681/
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=35005; int n,m,a ,mn ,f ,h ,cnt; long long g ,s1 ,s2 ; struct qwe { int ne,to; }e[N<<1]; int read() { int r=0,f=1; char p=getchar(); while(p>'9'||p<'0') { if(p=='-') f=-1; p=getchar(); } while(p>='0'&&p<='9') { r=r*10+p-48; p=getchar(); } return r*f; } void add(int u,int v) { cnt++; e[cnt].ne=h[u]; e[cnt].to=v; h[u]=cnt; } int ef(int x) { int l=1,r=m,ans=0; while(l<=r) { int mid=(l+r)>>1; if(mn[mid]<=x) l=mid+1,ans=mid; else r=mid-1; } return ans; } int main() { n=read(); for(int i=1;i<=n;i++) a[i]=read()-i; a[++n]=1e9; memset(mn,0x3f,sizeof(mn)); mn[0]=-1e9; for(int i=1;i<=n;i++) { int nw=ef(a[i]); f[i]=nw+1; m=max(m,f[i]); mn[nw+1]=min(mn[nw+1],a[i]); } for(int i=n;i>=0;i--) { add(f[i],i); g[i]=1e18; } g[0]=0;a[0]=-1e9; for(int x=1;x<=n;x++) for(int i=h[f[x]-1];i&&e[i].to<=x;i=e[i].ne) if(a[e[i].to]<=a[x]) { for(int j=e[i].to;j<=x;j++) s1[j]=abs(a[e[i].to]-a[j]),s2[j]=abs(a[x]-a[j]); for(int j=e[i].to+1;j<=x;j++) s1[j]+=s1[j-1],s2[j]+=s2[j-1]; for(int j=e[i].to;j<x;j++) g[x]=min(g[x],g[e[i].to]+s1[j]-s1[e[i].to]+s2[x]-s2[j]); } printf("%d\n%lld\n",n-f ,g ); return 0; }
相关文章推荐
- bzoj 1049 [HAOI2006]数字序列
- [bzoj] 1049: [HAOI2006]数字序列
- BZOJ1049: [HAOI2006]数字序列
- [bzoj 1049] HAOI2006数字序列
- 1049: [HAOI2006]数字序列 - BZOJ
- BZOJ1049: [HAOI2006]数字序列
- BZOJ1049 [HAOI2006]数字序列0
- bzoj1049: [HAOI2006]数字序列
- BZOJ 1049([HAOI2006]数字序列-数字序列LIS与分块)
- bzoj1049[HAOI2006]数字序列
- 【bzoj1049】[HAOI2006]数字序列
- bzoj1049 [HAOI2006]数字序列
- 【bzoj1049】【HAOI2006】【数字序列】
- [bzoj1049][HAOI2006]数字序列
- BZOJ 1049 [HAOI2006]数字序列 DP
- bzoj1049: [HAOI2006]数字序列
- 【bzoj1049】【HAOI2006】【数字序列】【dp+暴力】
- [bzoj1049][HAOI2006]数字序列
- 【BZOJ 1049】 [HAOI2006]数字序列
- 【BZOJ】1049: [HAOI2006]数字序列(lis+特殊的技巧)