BZOJ1049: [HAOI2006]数字序列
2017-04-06 07:45
429 查看
这题数列不随机没法做….
首先每个ai=ai-i,这样就把最长上升子序列变成了最长不降子序列
第一问,补集转化,改变的数最少就是不变的数最多,求最长不降子序列长度即可
第二问,
然后,求出每个数在最长不降子序列中排第几位,那么就可以DP了,f[i]表示1~i变成以i结尾的不降序列改变的绝对值之和最小值,设i在1~i以i为结尾的最长不降子中排第a位,那么f[i]只能由f[j](j< i,a[j]< a[i] , j在1~j以j为结尾的最长不降子中排a-1位)转移到,j+1~i-1的数一部分变成a[j],一部分变成a[i],枚举断点即可
这样做理论复杂度是O(n3)的,但是可以加一些如邻接表这样的优化,在随机数据下表现良好…….
code:
首先每个ai=ai-i,这样就把最长上升子序列变成了最长不降子序列
第一问,补集转化,改变的数最少就是不变的数最多,求最长不降子序列长度即可
第二问,
然后,求出每个数在最长不降子序列中排第几位,那么就可以DP了,f[i]表示1~i变成以i结尾的不降序列改变的绝对值之和最小值,设i在1~i以i为结尾的最长不降子中排第a位,那么f[i]只能由f[j](j< i,a[j]< a[i] , j在1~j以j为结尾的最长不降子中排a-1位)转移到,j+1~i-1的数一部分变成a[j],一部分变成a[i],枚举断点即可
这样做理论复杂度是O(n3)的,但是可以加一些如邻接表这样的优化,在随机数据下表现良好…….
code:
#include<set> #include<map> #include<deque> #include<queue> #include<stack> #include<cmath> #include<ctime> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<climits> #include<complex> #include<iostream> #include<algorithm> #define ll long long #define lowbit(x) x&(-x) #define inf 1e12 using namespace std; inline void up(int &x,const int &y){if(x<y)x=y;} inline void swap(int &x,int &y){x^=y;y^=x;x^=y;} inline int read() { char c; int x; while(!((c=getchar())>='0'&&c<='9')); x=c-'0'; while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0'; return x; } const int maxn = 31000; int n,a[maxn]; ll f[maxn],t1[maxn],t2[maxn]; int g[maxn]; struct node { int xx,x,i; node(){} node(const int &_x,const int &_i){x=_x;i=_i;} }seq[maxn]; bool cmp(const node x,const node y){return x.x==y.x?x.i<y.i:x.x<y.x;} int s[maxn]; void upd(int x,int c){for(;x<=n;x+=lowbit(x))up(s[x],c);} int query(int x) { int re=0; for(;x;x-=lowbit(x)) up(re,s[x]); return re; } struct edge { int y,nex; edge(){} edge(const int &_y,const int &_nex){y=_y;nex=_nex;} }e[maxn]; int len,fir[maxn]; inline void ins(const int x,const int y){e[++len]=edge(y,fir[x]);fir[x]=len;} ll LSH[maxn]; int main() { memset(fir,0,sizeof fir); len=0; n=read(); for(int i=1;i<=n;i++) { a[i]=read()-i; seq[i]=node(a[i],i); } sort(seq+1,seq+n+1,cmp); seq[0].x=seq[1].x-1; for(int i=1,k=0;i<=n;i++) { if(seq[i].x!=seq[i-1].x) LSH[++k]=seq[i].x; seq[i].xx=k; } int mx=0; for(int i=1;i<=n;i++) { int j=seq[i].i; a[j]=seq[i].xx; g[j]=query(j)+1; up(mx,g[j]); upd(j,g[j]); } ins(0,0); f[0]=0ll; for(int i=1;i<=n;i++) { f[i]=inf; for(int k=fir[g[i]-1];k;k=e[k].nex) { const int y=e[k].y; if(a[y]>a[i]) break; t1[y]=0; t2[i]=t2[i+1]=0; for(int j=y+1;j<i;j++) t1[j]=t1[j-1]+abs(LSH[a[y]]-LSH[a[j]]); ll temp=inf; for(int j=i;j>y;j--) { t2[j]=t2[j+1]+abs(LSH[a[i]]-LSH[a[j]]); if(t1[j-1]+t2[j]<temp) temp=t1[j-1]+t2[j]; } if(y==0) temp=t2[1]; if(temp==inf) temp=0; temp+=f[y]; if(f[i]>temp) f[i]=temp; } ins(g[i],i); if(g[i]==mx) for(int j=i+1;j<=n;j++) f[i]+=abs(LSH[a[j]]-LSH[a[i]]); } int ans1=0; ll ans=inf; for(int i=1;i<=n;i++) { if(ans1<g[i]) ans1=g[i],ans=f[i]; else if(ans1==g[i]&&ans>f[i]) ans=f[i]; } printf("%d\n%lld\n",n-ans1,ans); return 0; }
相关文章推荐
- BZOJ 1049([HAOI2006]数字序列-数字序列LIS与分块)
- bzoj1049: [HAOI2006]数字序列
- [bzoj1049][HAOI2006]数字序列
- bzoj1049: [HAOI2006]数字序列
- 【BZOJ 1049】 1049: [HAOI2006]数字序列 (LIS+动态规划)
- 1049: [HAOI2006]数字序列 - BZOJ
- [BZOJ1049][HAOI2006]数字序列(dp)
- 【bzoj1049】【HAOI2006】【数字序列】
- BZOJ 1049: [HAOI2006]数字序列
- 【BZOJ 1049】 [HAOI2006]数字序列
- [bzoj1049][HAOI2006]数字序列
- BZOJ1049 [HAOI2006]数字序列0
- bzoj 1049 [HAOI2006]数字序列
- bzoj1049 [HAOI2006]数字序列
- 【bzoj1049】[HAOI2006]数字序列
- BZOJ1049: [HAOI2006]数字序列
- bzoj 1049: [HAOI2006]数字序列【dp+二分+瞎搞】
- bzoj1049 [HAOI2006]数字序列 ( LIS + 区间DP)
- bzoj1049[HAOI2006]数字序列
- BZOJ 1049 [HAOI2006]数字序列 DP