决策单调性_笔记 gym 102904B Dispatch Money题解
发布日期:2021-05-06 15:54:47 浏览次数:26 分类:原创文章

本文共 2394 字,大约阅读时间需要 7 分钟。

决策单调性

判断决策单调性可以选择打表,有个比较好用的判断是这样的。

d p dp dp 转移式: f ( i ) = min ⁡ j < i { f ( j ) + c a l c ( j , i ) } f(i)=\min_{j<i}\{ f(j)+calc(j,i)\} f(i)=minj<i{ f(j)+calc(j,i)}

如果任意 a < b a<b a<b 满足 c a l c ( a , b + 1 ) + c a l c ( a + 1 , b ) ≤ c a l c ( a , b ) + c a l c ( a + 1 , b + 1 ) calc(a,b+1)+calc(a+1,b)\le calc(a,b)+calc(a+1,b+1) calc(a,b+1)+calc(a+1,b)calc(a,b)+calc(a+1,b+1) ,则 f ( i ) f(i) f(i) 具有决策单调性。

决策单调性优化 d p dp dp

  • 分治做法

    处理 s o l v e ( l , r , q l , q r ) solve(l,r,q_l,q_r) solve(l,r,ql,qr) ,意思是 q l q_l ql ~ q r q_r qr 的决策点在 l l l ~ r r r 之中,现在要分治求 q l q_l ql ~ q r q_r qr 的决策点。

    m i d = q l + q 2 2 mid=\frac{q_l+q_2}{2} mid=2ql+q2 ,遍历 l l l ~ r r r 求出 m i d mid mid 的决策点 p p p

    递归处理 s o l v e ( l , p , q l , m i d − 1 ) solve(l,p,q_l,mid-1) solve(l,p,ql,mid1) s o l v e ( l , p , m i d + 1 , q r ) solve(l,p,mid+1,q_r) solve(l,p,mid+1,qr)

    缺点:有些情况只是遍历 l l l ~ r r r 难求出 m i d mid mid 的决策点,这时候要 c d q cdq cdq 分治里面套决这个分治 ,见例题。

  • 单调栈做法

    (我今天之前只会这种做法2333

    用单调栈维护若干个单元三元组 ( p , l , r ) (p,l,r) (p,l,r) 表示 l l l ~ r r r 的决策点为 p p p

    刚开始单调栈为空。

    每求出一个 f ( x ) f(x) f(x) ,就更新单调栈中的三元组,具体:从栈中取出一个三原组 ( p , l , r ) (p,l,r) (p,l,r) 然后 c h e c k check check f ( l ) f(l) f(l) x x x 转移过来更优还是 p p p 转移过来更优。如果 x x x 更优,就把这个三元组删除。否则就在 l l l ~ r r r 中二分出一个点 l ′ l' l 满足从 x x x 转移过来更优。最后把 ( x , l ′ , n ) (x,l',n) (x,l,n) 加入单调栈。

    P S PS PS :为什么可以这么做就不赘述了,其实挺显然的。

gym 102904B Dispatch Money

分治套分治做法+逆序对

#include <bits/stdc++.h>#define N 300005using namespace std;typedef long long ll;const ll inf=1e17;int n,co,a[N],x=1,y,t[N]; ll ans[N],cnt;int sum(int pos){    int res=0; for(;pos;pos-=pos&-pos) res+=t[pos]; return res; }void add(int pos,int c){    for(;pos<=n;pos+=pos&-pos) t[pos]+=c; }ll ask(int l,int r){   	while(x>l) cnt+=sum(a[x-1]), add(a[x-1],1), --x; 	while(y<r) cnt+=y-x+1-sum(a[y+1]), add(a[y+1],1), ++y; 	while(x<l) add(a[x],-1), cnt-=sum(a[x]), ++x; 	while(y>r) add(a[y],-1), cnt-=y-x-sum(a[y]), --y; 	return cnt; }void solve(int l,int r,int ql,int qr){   	if(ql>qr)return;	int mid=(ql+qr)>>1,v=0; ll now,m=inf;	for(int i=l;i<=r&&i<mid;i++)		if((now=(ans[i]+ask(i+1,mid)))<m) m=now,v=i; ans[mid]=min(m+co,ans[mid]);	solve(l,v,ql,mid-1),solve(v,r,mid+1,qr);}void cdq(int l,int r){   	if(l==r)return;	int mid=(l+r)>>1;	cdq(l,mid);	solve(l,mid,mid+1,r);	cdq(mid+1,r);}int main(){   	cin>>n>>co;	for(int i=1;i<=n;i++)		scanf("%d",&a[i]),ans[i]=inf;	cdq(0,n);	cout<<ans[n]<<endl;}
上一篇:HDU 6094 Rikka with K-Match 【wqs二分+轮廓线dp】
下一篇:21.2.19总结

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2025年03月23日 02时52分23秒