对于有i*j的项,考虑用斜率优化DP(任务安排)
http://poj.org/problem?id=1180 单调递增
1 memset(f,8,sizeof(f));f[0]=0; 2 FOR(i,1,n) 3 { 4 while(l<r && (f[q[l+1]]-f[q[l]])<=(sumc[q[l+1]]-sumc[q[l]])*(sumt[i]+s)) ++l; 5 f[i]=f[q[l]]-(sumt[i]+s)*sumc[q[l]]+sumt[i]*sumc[i]+s*sumc[n]; 6 while(l<r && (f[i]-f[q[r]])*(sumc[q[r]]-sumc[q[r-1]])<=(f[q[r]]-f[q[r-1]])*(sumc[i]-sumc[q[r]])) --r; 7 q[++r]=i; 8 }
https://www.lydsy.com/JudgeOnline/problem.php?id=2726 不单调,二分
1 FOR(i,1,n) 2 { 3 int L=l,R=r; 4 while(L<R) 5 { 6 int mid=(L+R)>>1; 7 if(f[q[mid+1]]-f[q[mid]]<=(s+sumt[i])*(sumc[q[mid+1]]-sumc[q[mid]])) L=mid+1; 8 else R=mid; 9 } 10 int p=q[L]; 11 f[i]=f[p]-(sumt[i]+s)*sumc[p]+sumt[i]*sumc[i]+s*sumc[n]; 12 while(l<r && (f[i]-f[q[r]])*(sumc[q[r]]-sumc[q[r-1]])<=(f[q[r]]-f[q[r-1]])*(sumc[i]-sumc[q[r]])) --r; 13 q[++r]=i; 14 }
单调队列和斜率优化是属于决策单调性的一种。而决策单调性是满足四边形不等式的前提下,满足i+1-n的转移点大于等于i的决策点。而基本实现方式是整体二分或者维护双端队列并且在双端队列上二分查找。
1.基于1D/1D的DP优化
一般来说,1D/1D的DP都能通过优化,在O(nlogn)O(nlogn)的时间复杂度之内转移完成。
例子:
1.f[i]=min/maxf[j]+s[j,i];f[i]=min/maxf[j]+s[j,i];(s[i,j]s[i,j]表示的是从j向i转移的时候,s[i,j]s[i,j]的每一项只与ii或jj相关,并且jj的选择区间是连续的)
单调队列!O(n)O(n)解决!
2.f[i]=min/maxf[j]+s[j,i]f[i]=min/maxf[j]+s[j,i];(s[i,j]s[i,j]表示的是从j向i转移的时候,s[i,j]s[i,j]的每一项只与ii或jj相关,jj的选择区间是满足一定性质的)
数据结构!O(nlogn)O(nlogn)解决!
3.f[i]=min/maxf[j]+s[j,i]f[i]=min/maxf[j]+s[j,i];(s[i,j]s[i,j]表示的是从j向i转移的时候,s[i,j]s[i,j]的每一项最多与calc(i)×calc(j)calc(i)×calc(j)相关,calc(i),calc(j)calc(i),calc(j)均有单调性,j的选择区间是连续的)
斜率优化!O(n)O(n)解决!
4.f[i]=min/maxf[j]+s[j,i]f[i]=min/maxf[j]+s[j,i];(s[i,j]s[i,j]表示的是从j向i转移的时候,s[i,j]s[i,j]的每一项最多与calc(i)×calc(j)calc(i)×calc(j)相关,calc(i),calc(j)calc(i),calc(j)均不一定具有单调性,但j的选择区间是连续的)
斜率优化+CDQ分治或者斜率优化+Splay维护动态凸包
5.f[i]=min/maxf[j]+s[j,i]f[i]=min/maxf[j]+s[j,i];(s[i,j]s[i,j]表示的是从j向i转移的时候,s[i,j]s[i,j]满足四边形不等式,jj的选择区间是连续的)
决策单调性
剩下的,大概我并不会了...但是上述的DP都可以优化到O(nlogn)O(nlogn)之内。
决策单调性:
满足四边形不等式。
设j1<j2<i1<i2j1<j2<i1<i2
那么满足如果i1i1从j2j2转移,那么i2i2必定不可能从j1j1转移。这个东西,每道题证明不同,就不写了。