poj3017 -- Cut the Sequence
题意大意:将长度为n的序列分成若干段,使每段之和不大于m,
且使各段中最大值之和最小,输出该值。
易知,f[i]:=min(f[j]+max(j+1,i));
f[i]表示前i个中划分出的最小值,max(l,r)只l,r中的最大值,转移条件为sum[j+1,i]<=m。
这个方程时间复杂度为o(n^2)的,承受不了,所以要优化。
我们假设当 max(j,i)=max(j+1,i),,也就是说a[i]不是(j,i)之间的最大
值,由于很明显f是递增的(这个不用证明吧),所以
f[j-1]+max(j,i)<=f[j]+max(j+1,i),也就是说j这个决策是不必要的,
所以只有a[j]为max(j,i)时j才为必要的决策
所以可以用单调队列来维护有效的决策
F[i]=max(f[q[x-1]]+a[q[x]])
因为队首决策不一定最优,所以用数据结构维护,我用的是堆,
但是还有一个问题,就是当x=h(队头)是,q[x-1]是不存在的,
所以我们必须加入一个非决策队头lm[i](使到i为止和不大于m的
左边界,预先处理出来)。。这个目测就行了。。
P.S:理论上没错,但是poj上discuss数据过了,但还是没ac。。。
不知怎的。。
1 /* 2 *Author:yzcstc 3 *Typical:dp+queue+dui 4 *Statue:unsolve; 5 *Time:2013.01.20 6 */ 7 #include <cstdio> 8 #include <iostream> 9 #include <fstream> 10 #include <cstring> 11 #include <fstream> 12 #include <string> 13 #include <cstdlib> 14 const int maxn=111010; 15 using namespace std; 16 17 struct oo{ 18 long long z; 19 int x; 20 }; 21 22 int n, lm[maxn] , q[maxn] ,p[maxn]; 23 long long m, sum[maxn], f[maxn], a[maxn], tot; 24 oo d[maxn],cc; 25 26 void init(){ 27 scanf("%d",&n); 28 scanf("%lld",&m); 29 for (int i=1; i <= n; ++i){ 30 scanf("%lld",&a[i]); 31 sum[i] = sum[i-1] + a[i]; 32 } 33 int l=0; 34 for (int i=1; i <= n; ++i){ 35 while (sum[i]-sum[l]>m) ++l; 36 lm[i]=l; 37 } 38 } 39 40 void updui(int i){ 41 int j=i << 1; 42 while (j <= tot){ 43 if (j<tot && d[j].z>d[j+1].z) ++j; 44 if (d[i].z > d[j].z){ 45 cc = d[i]; 46 d[i] = d[j]; 47 d[j] = cc; 48 p[d[i].x] = i; 49 p[d[j].x] = j; 50 i = j; 51 j <<= 1; 52 } else break; 53 } 54 } 55 56 void downdui(int i){ 57 int j =i >> 1; 58 while (j>0){ 59 if (d[i].z<d[j].z){ 60 cc = d[i]; 61 d[i] = d[j]; 62 d[j] = cc; 63 p[d[i].x] = i; 64 p[d[j].x] = j; 65 i =j; 66 j >>= 1; 67 } else break; 68 } 69 } 70 71 void solve(){ 72 int h = 1, t = 0 ; 73 tot = 0; 74 for (int i=1; i <= n; ++i){ 75 while (h <= t && sum[i]-sum[q[h]]>m){ 76 d[p[q[h]]] = d[tot]; 77 p[d[tot].x] = p[q[h]]; 78 --tot; 79 updui(p[q[h]]); 80 ++h; 81 } 82 83 while (h <= t && a[i] > a[q[t]]){ 84 d[p[q[t]]] = d[tot]; 85 p[d[tot].x] = p[q[t]]; 86 --tot; 87 updui(p[q[t]]); 88 --t; 89 } 90 91 ++t; 92 q[t]= i; 93 ++tot; 94 d[tot].x = i; 95 d[tot].z = f[q[t-1]]+a[i]; 96 p[i] =tot; 97 downdui(tot); 98 99 int tt=p[q[h]]; 100 d[tt].z = f[lm[i]] + a[q[h]]; 101 downdui(tt); 102 updui(tt); 103 f[i] = d[1].z; 104 } 105 printf("%lld\n",f[n]); 106 107 } 108 109 int main(){ 110 freopen("poj3017.in","r",stdin); 111 freopen("poj3017.out","w",stdout); 112 init(); 113 solve(); 114 }
浙公网安备 33010602011771号