A(fzu 1894)
普通的单调队列,trick是进队判断的符号选取(>=wa , >ac).
B(poj 2823)
没什么好说的 ,坑爹poj g++,tle ;c++,ac.
C(hdu 3415)
尝试封装了一下单调队列。。。感觉也没有方便多少.
1 #define maxn 100010 2 #define INF 1000000000 3 int a[maxn<<1],p[maxn<<1],n,k; 4 5 struct Que 6 { 7 int q[maxn<<1],front,tail,cmp; 8 void clear() {front = tail = 0;} 9 void ins(int id) 10 { 11 while (front<tail && a[id]*cmp>a[q[tail-1]]*cmp) tail--; 12 q[tail++] = id; 13 } 14 void keep(int range) 15 { 16 while (front<tail && q[tail-1]-q[front]>=range) front++; 17 } 18 int query(int id) { return q[id]; } 19 };Que q; 20 void input() 21 { 22 int i; 23 scanf("%d%d",&n,&k); 24 for ( i=1 ; i<=n ; i++ ) 25 { 26 scanf("%d",&a[i]); 27 a[i+n] = a[i]; p[i] = i; p[i+n] = p[i]; 28 } 29 for ( i=1 ; i<=2*n ; i++ ) a[i] = a[i-1]+a[i]; 30 } 31 void solv() 32 { 33 int i,l,r,sum; 34 l = r = sum = -INF; 35 q.clear(); 36 q.cmp = -1; 37 for ( i=0 ; i<2*n ; i++ ) 38 { 39 q.ins(i); 40 q.keep(k); 41 if (a[i+1]-a[q.query(q.front)] > sum) 42 { 43 l = p[q.query(q.front)]+1; 44 r = p[i+1]; 45 sum = a[i+1]-a[q.query(q.front)]; 46 }else if (a[i+1]-a[q.query(q.front)] == sum) 47 { 48 if (p[q.query(q.front)]+1<l) 49 { 50 l = p[q.query(q.front)]+1; 51 r = p[i+1]; 52 }else if (p[q.query(q.front)]+1==l && p[i+1]<r) r=p[i+1]; 53 } 54 } 55 printf("%d %d %d\n",sum,l,r); 56 } 57 int main() 58 { 59 int cas; 60 scanf("%d",&cas); 61 while (cas--) 62 { 63 input(); 64 solv(); 65 } 66 return 0; 67 }
D(hdu 3401)
先列出朴素的dp方程逐渐,分析出可以优化的地方:
递推优化: dp[i][j] = max(dp[i][j],dp[i-1][j]);
单调队列优化: dp[i][j] = max{ dp[i][j] , dp[i-w-1][q.head]+(j-q.head)*num };
trick是前w+1天不能进行买卖,要特判并跳过买卖的决策.
1 #include <cmath> 2 #include <ctime> 3 #include <queue> 4 #include <cstdio> 5 #include <string> 6 #include <cstring> 7 #include <iostream> 8 #include <algorithm> 9 using namespace std; 10 #define maxn 2020 11 #define INF 1000000000 12 int ap[maxn],bp[maxn],as[maxn],bs[maxn],t,maxp,w,dp[maxn][maxn]; 13 void input() 14 { 15 int i; 16 scanf("%d%d%d",&t,&maxp,&w); 17 for ( i=1 ; i<=t ; i++ ) scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]); 18 } 19 int q[maxn],front,tail; 20 void DP() 21 { 22 int i,j,k; 23 for ( i=1,dp[0][0]=0 ; i<=maxp ; i++ ) dp[0][i] = -INF; 24 for ( i=1 ; i<=t ; i++ ) 25 for ( j=0 ; j<=maxp ; j++ ) 26 { 27 if (j<=as[i]) dp[i][j] = -ap[i]*j; 28 else dp[i][j] = -INF; 29 } 30 for ( i=1 ; i<=t ; i++ ) 31 { 32 for ( j=0 ; j<=maxp ; j++ ) dp[i][j] = max(dp[i][j],dp[i-1][j]); 33 if ((k=i-w-1)<0) continue; 34 35 front = tail = 0; 36 // buy 37 for ( j=0 ; j<=maxp ; j++ ) 38 { 39 while (front<tail && j-q[front]>as[i]) front++; 40 while (front<tail && dp[k][j]+j*ap[i]>=dp[k][q[tail-1]]+q[tail-1]*ap[i]) tail--; 41 q[tail++] = j; 42 int tmp = dp[k][q[front]]-(j-q[front])*ap[i]; 43 // printf("dp[%d][%d] = max: %d , dp[%d][%d]-(%d-%d)*%d = %d\n",i,j,dp[i][j],k,q[front],j,q[front],ap[i],max(dp[i][j],tmp)); 44 dp[i][j] = max(dp[i][j],tmp); 45 } 46 47 front = tail = 0; 48 // sell 49 for ( j=maxp ; j>=0 ; j-- ) 50 { 51 while (front<tail && q[front]-j>bs[i]) front++; 52 while (front<tail && dp[k][j]+j*bp[i]>=dp[k][q[tail-1]]+q[tail-1]*bp[i]) tail--; 53 q[tail++] = j; 54 int tmp = dp[k][q[front]]-(j-q[front])*bp[i]; 55 // printf("dp[%d][%d] = max: %d , dp[%d][%d]-(%d-%d)*%d = %d\n",i,j,dp[i][j],k,q[front],j,q[front],bp[i],max(dp[i][j],tmp)); 56 dp[i][j] = max(dp[i][j],tmp); 57 } 58 } 59 int ans=-INF; 60 for ( i=0 ; i<=t ; i++ ) 61 for ( j=0 ; j<=maxp ; j++ ) ans = max(ans,dp[i][j]); 62 printf("%d\n",ans); 63 } 64 int main() 65 { 66 int cas; 67 scanf("%d",&cas); 68 while (cas--) 69 { 70 input(); 71 DP(); 72 } 73 return 0; 74 }
E(hdu 3530)
关键是求区间给定区间的最大值和最小值,有很多办法,在此题中,可以用单调队列做到O(n).
trick: 当最大-最小>k时需要删除队列元素维护,但是当小于m时不用进行删除操作,因为没用。。。
1 #include <cmath> 2 #include <ctime> 3 #include <queue> 4 #include <cstdio> 5 #include <string> 6 #include <cstring> 7 #include <iostream> 8 #include <algorithm> 9 using namespace std; 10 #define maxn 1000100 11 int n,m,k,a[maxn]; 12 int qs[maxn],ts,fs,ql[maxn],tl,fl,q[maxn],front,tail; 13 bool inq[maxn]; 14 void input() 15 { 16 int i; 17 for ( i=1 ; i<=n ; i++ ) scanf("%d",&a[i]); 18 } 19 int queryl() 20 { 21 while (fl<tl && !inq[ql[fl]]) fl++; 22 return a[ql[fl]]; 23 } 24 int querys() 25 { 26 while (fs<ts && !inq[qs[fs]]) fs++; 27 return a[qs[fs]]; 28 } 29 void solv() 30 { 31 int i,ans=0; 32 front = tail = fs = ts = fl = tl = 0; 33 for ( i=1 ; i<=n ; i++ ) 34 { 35 q[tail++] = i; 36 inq[i] = 1; 37 while (fs<ts && a[i]<a[qs[ts-1]]) ts--; 38 qs[ts++] = i; 39 while (fl<tl && a[i]>a[ql[tl-1]]) tl--; 40 ql[tl++] = i; 41 while(front<tail && queryl()-querys()>k) 42 { 43 inq[q[front]] = 0; 44 front++; 45 } 46 if (queryl()-querys()>=m && queryl()-querys()<=k) ans = max(ans,q[tail-1]-q[front]+1); 47 } 48 printf("%d\n",ans); 49 } 50 int main() 51 { 52 while (scanf("%d%d%d",&n,&m,&k)!=EOF) 53 { 54 input(); 55 solv(); 56 } 57 return 0; 58 }
F(poj3017)
非常有启发性的一题:利用线段树的单点更新更新单调队列里面的值.单调队列保证了快速获得区间最值,线段树的区间查询保证了答案的最优性.
1 #include <cmath> 2 #include <ctime> 3 #include <queue> 4 #include <cstdio> 5 #include <string> 6 #include <cstring> 7 #include <iostream> 8 #include <algorithm> 9 using namespace std; 10 typedef long long llong; 11 const llong INF = 1ll<<60; 12 #define maxn 100100 13 #define ls (rt<<1) 14 #define rs (rt<<1|1) 15 #define mid ((l+r)>>1) 16 struct node 17 { 18 int l,r,big; 19 };node q[maxn]; 20 llong tree[maxn<<2],m,dp[maxn]; 21 int a[maxn],n,front,tail; 22 void buildtree(int l,int r,int rt) 23 { 24 tree[rt] = INF; 25 if (l == r) return; 26 buildtree(l,mid,ls); 27 buildtree(mid+1,r,rs); 28 } 29 void pushup(int rt) 30 { 31 tree[rt] = min(tree[ls],tree[rs]); 32 } 33 void ins(llong var,int pos,int l,int r,int rt) 34 { 35 if (l == r) 36 { 37 tree[rt] = var; 38 return; 39 } 40 if (pos<=mid) ins(var,pos,l,mid,ls); 41 else ins(var,pos,mid+1,r,rs); 42 pushup(rt); 43 } 44 llong query(int L,int R,int l,int r,int rt) 45 { 46 llong res1,res2; 47 res1 = res2 = INF; 48 if (L<=l && r<=R) return tree[rt]; 49 if (L<=mid) res1 = query(L,R,l,mid,ls); 50 if (R>mid) res2 = query(L,R,mid+1,r,rs); 51 return min(res1,res2); 52 } 53 llong solv() 54 { 55 int i,lft; 56 llong cnt=0; 57 node tmp; 58 buildtree(0,n,1); 59 front = tail = 0; 60 for ( i=1 ; i<=n ; i++ ) 61 if (a[i]>m) return -1; 62 for ( lft=i=1,dp[0]=0 ; i<=n ; i++ ) 63 { 64 cnt += a[i]; 65 while (cnt>m) 66 { 67 q[front].l++; 68 if (q[front].l>q[front].r) 69 { 70 ins(INF,front,0,n,1); 71 front++; 72 }else ins(dp[q[front].l-1]+q[front].big,front,0,n,1); 73 cnt -= a[lft++]; 74 } 75 tmp.l = tmp.r = i; tmp.big = a[i]; 76 while (front<tail && tmp.big>=q[tail-1].big) 77 { 78 tmp.l = q[tail-1].l; //merge 79 ins(INF,tail-1,0,n,1); 80 tail--; 81 } 82 q[tail++] = tmp; 83 ins(dp[q[tail-1].l-1]+q[tail-1].big,tail-1,0,n,1); 84 dp[i] = query(front,tail-1,0,n,1); 85 // printf("dp[%d]=%I64d\n",i,dp[i]); 86 } 87 return dp[n]; 88 } 89 int main() 90 { 91 while (scanf("%d%I64d",&n,&m)!=EOF) 92 { 93 for (int i=1 ; i<=n ; i++ ) scanf("%d",&a[i]); 94 printf("%I64d\n",solv()); 95 } 96 return 0; 97 }
G(poj3245)
为了满足 " 当p<q 时 , Bp > Aq " 的条件,需要先将数据预处理成块状, 即 对所有p ,要找到最大的q 使得 Bp <= Aq .
这是第一步,朴素做法O(n^2) , 用一点技巧可以做到nlogn : 线段树(比较麻烦,可能要离散化,代码量大) 或者 分别对A和对B降序排序O(nlogn) ,再用2个指针扫描 O(n) , 要记得记录排序前的原始下标.
第二步,在limt的限制下求最小sum的分组方法, 很容易想到要二分答案.
第三步,对于二分的sum值,需要一个验证办法.注意,让每组尽量接近sum的贪心分组办法是错的, 因为这里还要考虑到 ΣMi 的限制.
老老实实dp:
dp[i]表示以第i个为结尾, ΣM 最小的分组方法.
dp[i] = min {dp[j] + max{aj+1,...,ai} }.
这个方程和F题的非常相似,把决策存在单调队列里,用线段树得到最优值.
1 #include <cmath> 2 #include <ctime> 3 #include <queue> 4 #include <cstdio> 5 #include <string> 6 #include <cstring> 7 #include <iostream> 8 #include <algorithm> 9 using namespace std; 10 typedef long long llong; 11 #define maxn 50100 12 #define ls (rt<<1) 13 #define rs ((rt<<1)+1) 14 #define mid ((l+r)>>1) 15 #define BIG 1 16 #define SML 0 17 #define INF (1ll<<31) 18 struct node 19 { 20 int a,b,id; 21 };node p[maxn],sa[maxn],sb[maxn],e[maxn]; 22 llong init[2]; 23 llong sumb[maxn],tree[maxn<<2]; 24 int n,lmt,cnte,lst[maxn]; 25 26 bool cmpa(const node& u,const node& v) { return u.a>v.a; } 27 bool cmpb(const node& u,const node& v) { return u.b>v.b; } 28 llong query_big(int L,int R,int l,int r,int rt) 29 { 30 llong resl,resr; 31 resl = resr = init[BIG]; 32 if (L<=l && r<=R) return tree[rt]; 33 if (L<=mid) resl = query_big(L,R,l,mid,ls); 34 if (R>mid) resr = query_big(L,R,mid+1,r,rs); 35 return max(resl,resr); 36 } 37 llong query_sml(int L,int R,int l,int r,int rt) 38 { 39 llong resl,resr; 40 resl = resr = init[SML]; 41 if (L<=l && r<=R) return tree[rt]; 42 if (L<=mid) resl = query_sml(L,R,l,mid,ls); 43 if (R>mid) resr = query_sml(L,R,mid+1,r,rs); 44 return min(resl,resr); 45 } 46 void buildtree(int l,int r,int rt,int flg) 47 { 48 tree[rt] = init[flg]; 49 if (l==r) return; 50 buildtree(l,mid,ls,flg); 51 buildtree(mid+1,r,rs,flg); 52 } 53 void pushup(int rt,int flg) 54 { 55 if (flg==BIG) tree[rt] = max(tree[ls],tree[rs]); 56 else tree[rt] = min(tree[rs],tree[ls]); 57 } 58 void ins(int val,int pos,int l,int r,int rt,int flg) 59 { 60 if (l==r) { tree[rt]=val; return; } 61 if (pos<=mid) ins(val,pos,l,mid,ls,flg); 62 else ins(val,pos,mid+1,r,rs,flg); 63 pushup(rt,flg); 64 } 65 void pretreat() 66 { 67 int i,j,k; 68 buildtree(1,n,1,BIG); 69 for ( i=1 ;i<=n ; i++ ) sa[i]=p[i], sb[i]=p[i]; 70 sort(sa+1,sa+1+n,cmpa); sort(sb+1,sb+1+n,cmpb); 71 // for ( i=1 ; i<=n ; i++ ) printf("sa: a=%d id=%d\nsb: b=%d id=%d\n\n",sa[i].a,sa[i].id,sb[i].b,sb[i].id); 72 for ( i=j=1,k=0 ; i<=n ; i++ ) 73 { 74 lst[ sb[i].id ] = sb[i].id; 75 while (j<=n && sa[j].a>=sb[i].b) k=max(k,sa[j].id),j++; 76 lst[ sb[i].id ] = max(sb[i].id,k); 77 ins(lst[ sb[i].id ],sb[i].id,1,n,1,BIG); 78 } 79 for ( i=1 ; i<=n ; i++ ) 80 lst[i] = query_big(i,lst[i],1,n,1); 81 buildtree(1,n,1,BIG); 82 for ( i=1 ; i<=n ; i++ ) sumb[i] = sumb[i-1] + p[i].b; 83 for ( i=1 ; i<=n ; i++ ) ins(p[i].a,i,1,n,1,BIG); 84 for ( i=1,cnte=0 ; i<=n ; i++ ) 85 { 86 e[++cnte].a = query_big(i,lst[i],1,n,1); 87 e[cnte].b = sumb[lst[i]] - sumb[i-1]; 88 e[cnte].id = cnte; 89 i = lst[i]; 90 } 91 // for ( i=1 ; i<=cnte ; i++ ) printf("e[%d]: a=%d b=%d\n",i,e[i].a,e[i].b); 92 for ( i=1 ; i<=cnte ; i++ ) sumb[i] = sumb[i-1] + e[i].b; 93 } 94 struct node2 95 { 96 int l,r,big; 97 };node2 q[maxn]; 98 99 int front,tail; 100 llong dp[maxn]; 101 int check(int sum) 102 { 103 int i,lft; 104 llong cnt=0; 105 node2 tmp; 106 107 front = tail = 0; 108 for ( i=1 ; i<=cnte ; i++ ) if (e[i].b>sum) return 0; 109 110 for ( i=lft=1 ; i<=cnte ; i++ ) 111 { 112 cnt += e[i].b; 113 while (cnt>sum) 114 { 115 q[front].l++; 116 if (q[front].l>q[front].r) 117 { 118 ins(init[SML],front,0,n,1,SML); 119 front++; 120 }else ins(dp[q[front].l-1]+q[front].big,front,0,n,1,SML); 121 cnt -= e[lft++].b; 122 } 123 tmp.l = tmp.r = i; tmp.big = e[i].a; 124 while (front<tail && tmp.big>=q[tail-1].big) 125 { 126 tmp.l = q[tail-1].l; 127 ins(init[SML],tail-1,0,n,1,SML); 128 tail--; 129 } 130 q[tail++] = tmp; 131 ins(dp[tmp.l-1]+tmp.big,tail-1,0,n,1,SML); 132 dp[i] = query_sml(front,tail-1,0,n,1); 133 } 134 if (dp[cnte]<=lmt) return 1; 135 else return 0; 136 } 137 int solv() 138 { 139 int l,r; 140 l = 0; r = sumb[n]; 141 while (l<r) 142 { 143 if (check(mid)) r=mid; 144 else l=mid+1; 145 } return r; 146 } 147 int main() 148 { 149 init[BIG] = 0; init[SML] = INF; 150 scanf("%d%d",&n,&lmt); 151 for (int i=1 ; i<=n ; i++ ) { scanf("%d%d",&p[i].a,&p[i].b); p[i].id=i; } 152 pretreat(); 153 int ans = solv(); 154 printf("%d\n",ans); 155 return 0; 156 }
斜率优化dp:
H(hdu 2993)
1 #include <cmath> 2 #include <ctime> 3 #include <queue> 4 #include <cstdio> 5 #include <string> 6 #include <cstring> 7 #include <iostream> 8 #include <algorithm> 9 using namespace std; 10 typedef long long llong; 11 #define maxn 100100 12 #define ls (rt<<1) 13 #define rs ((rt<<1)+1) 14 #define mid ((l+r)<<1) 15 int sum[maxn]; 16 int n,m; 17 int q[maxn],front,tail; 18 19 double g(int a,int b) 20 { 21 double res = (double)(sum[b]-sum[a-1])/(double)(b-a+1.0); 22 return res; 23 } 24 void solv() 25 { 26 int i; 27 double ans=0; 28 front = tail = 0; 29 for ( i=m ; i<=n ; i++ ) 30 { 31 while (front+1<tail && g(q[tail-2],q[tail-1])>g(q[tail-1],i-m+1)) tail--; 32 q[tail++] = i-m+1; 33 while (front+1<tail && g(q[front],i)<=g(q[front+1],i)) front++; 34 ans = max(ans,g(q[front],i)); 35 } 36 printf("%.2lf\n",ans); 37 } 38 int GetInt() 39 { 40 char ch=getchar(); 41 while(ch<'0'||ch>'9')ch=getchar(); 42 int num=0; 43 while(ch>='0'&&ch<='9'){ 44 num=num*10+ch-'0'; 45 ch=getchar(); 46 } 47 return num; 48 } 49 int main() 50 { 51 while (scanf("%d%d",&n,&m)!=EOF) 52 { 53 for (int i=1 ; i<=n ; i++ ) 54 { 55 sum[i] = GetInt(); 56 sum[i] += sum[i-1]; 57 } 58 solv(); 59 } 60 return 0; 61 }
I(hdu 2829)
1 #include <cmath> 2 #include <ctime> 3 #include <queue> 4 #include <cstdio> 5 #include <string> 6 #include <cstring> 7 #include <iostream> 8 #include <algorithm> 9 using namespace std; 10 #define maxn 1010 11 typedef long long llong; 12 #define ls (rt<<1) 13 #define rs ((rt<<1)+1) 14 #define mid ((l+r)<<1) 15 const llong INF = 1ll<<62; 16 llong dp[maxn][maxn],v[maxn],sum[maxn]; 17 int n,m,a[maxn]; 18 19 void init() 20 { 21 int i; 22 for ( i=1 ; i<=n ; i++ ) sum[i] = sum[i-1]+a[i]; 23 for ( i=1 ; i<=n ; i++ ) v[i] = v[i-1]+sum[i-1]*a[i]; 24 } 25 int q[maxn],front,tail; 26 27 llong w(int j,int i) 28 { 29 return v[i]-v[j]-sum[j]*(sum[i]-sum[j]); 30 } 31 int x; 32 double g(int id,int a,int b) 33 { 34 double xa,xb,ya,yb; 35 ya = dp[id][a] - v[a]+sum[a]*sum[a]; xa = sum[a]; 36 yb = dp[id][b] - v[b]+sum[b]*sum[b]; xb = sum[b]; 37 return (ya-yb) / (xa-xb); 38 } 39 void DP() 40 { 41 int i,j; 42 for ( i=0 ; i<=n ; i++ ) dp[0][i] = v[i]; 43 // for ( i=0 ; i<=n ; i++ ) printf("dp[0][%d]=%I64d\n",i,dp[0][i]); printf("\n"); 44 45 for ( i=1 ; i<=m ; i++ ) 46 { 47 front = tail = 0; 48 q[tail++] = i; 49 for ( j=i+1 ; j<=n ; j++ ) 50 { 51 x = j; 52 while (front+1<tail && g(i-1,q[front],q[front+1])<=(double)sum[j]) front++; 53 dp[i][j] = dp[i-1][q[front]] + w(q[front],j); 54 // printf("dp[%d][%d] = %I64d q[front]=%d\n",i,j,dp[i][j],q[front]); 55 while (front+1<tail && g(i-1,q[tail-2],q[tail-1])>=g(i-1,q[tail-1],j)) tail--; 56 q[tail++] = j; 57 } 58 } 59 llong res=INF; 60 for ( i=0 ; i<=m ; i++ ) res = min(res,dp[i][n]); 61 cout<<res<<endl; 62 } 63 int main() 64 { 65 while (scanf("%d%d",&n,&m)!=EOF) 66 { 67 if (!n && !m) break; 68 for (int i=1 ; i<=n ; i++ ) scanf("%d",&a[i]); 69 init(); 70 DP(); 71 } 72 return 0; 73 }
J(hdu 3507)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <queue> 6 #include <vector> 7 using namespace std; 8 typedef long long llong; 9 #define maxn 600010 10 llong dp[maxn],sum[maxn]; 11 int a[maxn],n,m,q[maxn],front,tail; 12 13 double dx(int a,int b){return (double)(sum[a]-sum[b]);} 14 double dy(int a,int b){return (double)(dp[a]+sum[a]*sum[a]-dp[b]-sum[b]*sum[b]);} 15 int check(int a,int b,llong c) 16 { 17 llong resa = dp[a] + (sum[a]-c)*(sum[a]-c); 18 llong resb = dp[b] + (sum[b]-c)*(sum[b]-c); 19 if (resa>resb) return 1; 20 else return 0; 21 } 22 void solv() 23 { 24 int i; 25 for ( i=1 ; i<=n ; i++ ) sum[i] = sum[i-1] + a[i]; 26 front = tail = 0; 27 q[tail++] = 0; 28 for ( i=1 ; i<=n ; i++ ) 29 { 30 while (front+1<tail && check(q[front],q[front+1],sum[i])) front++; 31 dp[i] = dp[q[front]] + (sum[i]-sum[q[front]]) * (sum[i]-sum[q[front]])+m; 32 // printf("dp[%d] = %lld\n",i,dp[i]); 33 while (front+1<tail && dy(q[tail-1],q[tail-2]) * dx(i,q[tail-1]) >= dx(q[tail-1],q[tail-2]) * dy(i,q[tail-1])) tail--; 34 q[tail++] = i; 35 } 36 cout<<dp[n]<<endl; 37 } 38 int main() 39 { 40 while (scanf("%d%d",&n,&m)!=EOF) 41 { 42 for (int i=1 ; i<=n ; i++ ) scanf("%d",&a[i]); 43 solv(); 44 } 45 return 0; 46 }
I,J需要比较决策得到斜率形式,比较决策的形式:
i<j<k 时 g(i,j)<常数c可推出j更优 ,g(i,j)<g(j,k)<常数c 可推出决策j不会为最优可从集合中去掉
H不需要比较决策直接是斜率形式.
设i<j<k , g(i,j)>g(j,k) 可以通过图像知道上凸点j不会成为最优决策.