您的位置:首页 > 其它

【专题】单调队列/斜率优化DP

2013-07-25 11:04 183 查看

一、单调队列

志愿者选拔 O(n)

struct STU{
char name[7];
int rp;
};

int que[2111111];
int idx[2111111];

int main()
{
int T,head,tail;
char gs[111];
scanf("%d",&T);
while (T--)
{
int cas,cnt;
head=tail=0;
cas=cnt=0;
while (scanf("%s",gs))
{
if (strcmp(gs,"END")==0) break;
if (strcmp(gs,"C")==0)
{
cnt++;
STU tmp;
scanf("%s%d",tmp.name,&tmp.rp);
while (head<tail&&que[tail-1]<=tmp.rp) tail--;
idx[tail]=cnt;
que[tail++]=tmp.rp;
}
if (strcmp(gs,"G")==0)
{
cas++;
if (idx[head]<=cas) head++;
}
if (strcmp(gs,"Q")==0)
{
if (head<tail) cout<<que[head]<<endl;
else cout<<-1<<endl;
}
}
}
return 0;
}


Sliding
Window O(n)

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

const int maxn=1111111;

int a[maxn];
int que[maxn];
int idx[maxn];

int main()
{
int n,k;
int head,tail,cas;
while (~scanf("%d%d",&n,&k))
{
for (int i=0;i<n;i++) scanf("%d",&a[i]);
head=tail=cas=0;
for (int i=0;i<n;i++)
{
while (head<tail&&que[tail-1]>=a[i]) tail--;
idx[tail]=i;
que[tail++]=a[i];
while (head<tail&&i-idx[head]>=k) head++;
if (i>=k-1) cout<<que[head]<<" ";
else if (i>=k-1&&i==n-1) cout<<que[head];
}
cout<<endl;
head=tail=cas=0;
for (int i=0;i<n;i++)
{
while (head<tail&&que[tail-1]<=a[i]) tail--;
idx[tail]=i;
que[tail++]=a[i];
while (head<tail&&i-idx[head]>=k) head++;
if (i>=k-1&&i<n-1) cout<<que[head]<<" ";
else if (i>=k-1&&i==n-1) cout<<que[head];
}
cout<<endl;
}
return 0;
}


Max
Sum of Max-K-sub-sequence O(n)

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int a[411111];
int f[411111];
int que[1111111];
int pt[1111111];
int n,k;
int T;
int head,tail;
int sum[411111];
int max_sum,start,end;

int main()
{
scanf("%d",&T);
while (T--)
{
memset(f,0,sizeof(f));
memset(que,0,sizeof(que));
memset(pt,0,sizeof(pt));
memset(sum,0,sizeof(sum));
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i+n]=a[i];
}
for (int i=1;i<=n+k;i++)
{
sum[i]+=sum[i-1]+a[i];
}
//f[i]=max(sum[i]-sum[k]);
head=tail=0;
max_sum=start=end=-1e9;
for (int i=1;i<=n+k;i++)
{
while ((head<tail)&&(i-pt[head]>k)) head++;
while ((head<tail)&&(sum[i-1]<=que[tail-1])) tail--;
que[tail]=sum[i-1],pt[tail++]=i-1;
f[i]=sum[i]-que[head];
if (f[i]>max_sum)
{
max_sum=f[i];
start=pt[head]+1;
end=i;
}
}
if (start>n) start=start-n;
if (end>n) end=end-n;
printf("%d %d %d\n",max_sum,start,end);
}
return 0;
}


二、单调队列dp

Trade O(n)

/** head-file **/

#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <algorithm>

/** define-for **/

#define REP(i, n) for (int i=0;i<int(n);++i)
#define FOR(i, a, b) for (int i=int(a);i<int(b);++i)
#define DWN(i, b, a) for (int i=int(b-1);i>=int(a);--i)
#define REP_1(i, n) for (int i=1;i<=int(n);++i)
#define FOR_1(i, a, b) for (int i=int(a);i<=int(b);++i)
#define DWN_1(i, b, a) for (int i=int(b);i>=int(a);--i)
#define REP_N(i, n) for (i=0;i<int(n);++i)
#define FOR_N(i, a, b) for (i=int(a);i<int(b);++i)
#define DWN_N(i, b, a) for (i=int(b-1);i>=int(a);--i)
#define REP_1_N(i, n) for (i=1;i<=int(n);++i)
#define FOR_1_N(i, a, b) for (i=int(a);i<=int(b);++i)
#define DWN_1_N(i, b, a) for (i=int(b);i>=int(a);--i)

/** define-useful **/

#define clr(x,a) memset(x,a,sizeof(x))
#define sz(x) int(x.size())
#define see(x) cerr<<#x<<" "<<x<<endl
#define se(x) cerr<<" "<<x
#define pb push_back
#define mp make_pair

/** test **/

#define Display(A, n, m) {                      \
REP(i, n){                                  \
REP(j, m) cout << A[i][j] << " ";       \
cout << endl;                           \
}                                           \
}

#define Display_1(A, n, m) {                    \
REP_1(i, n){                                \
REP_1(j, m) cout << A[i][j] << " ";     \
cout << endl;                           \
}                                           \
}

using namespace std;

/** typedef **/

typedef long long LL;

/** Add - On **/

const int direct4[4][2]={ {0,1},{1,0},{0,-1},{-1,0} };
const int direct8[8][2]={ {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int direct3[6][3]={ {1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1} };

const int MOD = 1000000007;
const int INF = 0x3f3f3f3f;
const long long INFF = 1LL << 60;
const double EPS = 1e-9;
const double OO = 1e15;
const double PI = acos(-1.0); //M_PI;

const int maxn=2222;
int f[maxn][maxn];
int AP[maxn],BP[maxn],AS[maxn],BS[maxn];
int MaxP,W,T;
/**
f[i][j]=max(f[i-1][j],f[i-W-1][k]-AP[i]*(j-k),f[i-W-1][k]+BP[i]*(k-j))
f[i-W-1][k]-AP[i]*(j-k)
=f[i-W-1][k]+AP[i]*k-AP[i]*j
f[i-W-1][k]+BP[i]*(k-j)
=f[i-W-1][k]+BP[i]*k-BP[i]*j
**/
int que[maxn];
int idx[maxn];

int main()
{
int CAS;
int head,tail,ans;
scanf("%d",&CAS);
while (CAS--)
{
scanf("%d%d%d",&T,&MaxP,&W);
REP_1(i,T)
{
scanf("%d%d%d%d",&AP[i],&BP[i],&AS[i],&BS[i]);
}
REP_1(i,MaxP) f[0][i]=-INF;
f[0][0]=0;
ans=0;
FOR_1(i,1,T)
{
FOR_1(j,0,MaxP) f[i][j]=f[i-1][j];
if (i-W-1<1)
{
FOR_1(j,0,AS[i]) f[i][j]=max(f[i][j],-AP[i]*j);
continue;
}
head=tail=0;
FOR_1(j,0,MaxP)
{
while (head<tail&&que[tail-1]<=f[i-W-1][j]+AP[i]*j) tail--;
que[tail]=f[i-W-1][j]+AP[i]*j;
idx[tail++]=j;
while (head<tail&&j-idx[head]>AS[i]) head++;
f[i][j]=max(f[i][j],que[head]-AP[i]*j);
ans=max(ans,f[i][j]);
}
head=tail=0;
DWN_1(j,MaxP,0)
{
while (head<tail&&que[tail-1]<=f[i-W-1][j]+BP[i]*j) tail--;
que[tail]=f[i-W-1][j]+BP[i]*j;
idx[tail++]=j;
while (head<tail&&idx[head]-j>BS[i]) head++;
f[i][j]=max(f[i][j],que[head]-BP[i]*j);
ans=max(ans,f[i][j]);
}
}
cout<<ans<<endl;
}
return 0;
}


SubsequenceO(n)

/** head-file **/

#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <algorithm>

/** define-for **/

#define REP(i, n) for (int i=0;i<int(n);++i)
#define FOR(i, a, b) for (int i=int(a);i<int(b);++i)
#define DWN(i, b, a) for (int i=int(b-1);i>=int(a);--i)
#define REP_1(i, n) for (int i=1;i<=int(n);++i)
#define FOR_1(i, a, b) for (int i=int(a);i<=int(b);++i)
#define DWN_1(i, b, a) for (int i=int(b);i>=int(a);--i)
#define REP_N(i, n) for (i=0;i<int(n);++i)
#define FOR_N(i, a, b) for (i=int(a);i<int(b);++i)
#define DWN_N(i, b, a) for (i=int(b-1);i>=int(a);--i)
#define REP_1_N(i, n) for (i=1;i<=int(n);++i)
#define FOR_1_N(i, a, b) for (i=int(a);i<=int(b);++i)
#define DWN_1_N(i, b, a) for (i=int(b);i>=int(a);--i)

/** define-useful **/

#define clr(x,a) memset(x,a,sizeof(x))
#define sz(x) int(x.size())
#define see(x) cerr<<#x<<" "<<x<<endl
#define se(x) cerr<<" "<<x
#define pb push_back
#define mp make_pair

/** test **/

#define Display(A, n, m) {                      \
REP(i, n){                                  \
REP(j, m) cout << A[i][j] << " ";       \
cout << endl;                           \
}                                           \
}

#define Display_1(A, n, m) {                    \
REP_1(i, n){                                \
REP_1(j, m) cout << A[i][j] << " ";     \
cout << endl;                           \
}                                           \
}

using namespace std;

/** typedef **/

typedef long long LL;

/** Add - On **/

const int direct4[4][2]={ {0,1},{1,0},{0,-1},{-1,0} };
const int direct8[8][2]={ {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int direct3[6][3]={ {1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1} };

const int MOD = 1000000007;
const int INF = 0x3f3f3f3f;
const long long INFF = 1LL << 60;
const double EPS = 1e-9;
const double OO = 1e15;
const double PI = acos(-1.0); //M_PI;
const int maxn=110000;
int a[maxn];
typedef pair<int,int> PII;
deque<PII>q1,q2;
int main()
{
int n,m,k;
int ans,now;
while (~scanf("%d%d%d",&n,&m,&k))
{
ans=0;
now=0;
q1.clear();
q2.clear();
REP(i,n)
{
scanf("%d",&a[i]);
while (!q1.empty()&&q1.back().first<=a[i]) q1.pop_back();
q1.push_back(mp(a[i],i));
while (!q2.empty()&&q2.back().first>=a[i]) q2.pop_back();
q2.push_back(mp(a[i],i));
while (!q1.empty()&&!q2.empty()&&q1.front().first-q2.front().first>k)
{
if (q1.front().second<q2.front().second)
{
now=q1.front().second+1;
q1.pop_front();
}
else
{
now=q2.front().second+1;
q2.pop_front();
}
}
if (!q1.empty()&&!q2.empty()&&q1.front().first-q2.front().first>=m)
ans=max(ans,i-now+1);
}
printf("%d\n",ans);
}
return 0;
}


其他题目

MUTC8
E- One hundred layer 单调队列dp

MUTC7
C - Dragon Ball 单调队列dp

三、斜率优化

MAX
Average Problem O(n)

/** head-file **/

#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <algorithm>

/** define-for **/

#define REP(i, n) for (int i=0;i<int(n);++i)
#define FOR(i, a, b) for (int i=int(a);i<int(b);++i)
#define DWN(i, b, a) for (int i=int(b-1);i>=int(a);--i)
#define REP_1(i, n) for (int i=1;i<=int(n);++i)
#define FOR_1(i, a, b) for (int i=int(a);i<=int(b);++i)
#define DWN_1(i, b, a) for (int i=int(b);i>=int(a);--i)
#define REP_N(i, n) for (i=0;i<int(n);++i)
#define FOR_N(i, a, b) for (i=int(a);i<int(b);++i)
#define DWN_N(i, b, a) for (i=int(b-1);i>=int(a);--i)
#define REP_1_N(i, n) for (i=1;i<=int(n);++i)
#define FOR_1_N(i, a, b) for (i=int(a);i<=int(b);++i)
#define DWN_1_N(i, b, a) for (i=int(b);i>=int(a);--i)

/** define-useful **/

#define clr(x,a) memset(x,a,sizeof(x))
#define sz(x) int(x.size())
#define see(x) cerr<<#x<<" "<<x<<endl
#define se(x) cerr<<" "<<x
#define pb push_back
#define mp make_pair

/** test **/

#define Display(A, n, m) {                      \
REP(i, n){                                  \
REP(j, m) cout << A[i][j] << " ";       \
cout << endl;                           \
}                                           \
}

#define Display_1(A, n, m) {                    \
REP_1(i, n){                                \
REP_1(j, m) cout << A[i][j] << " ";     \
cout << endl;                           \
}                                           \
}

using namespace std;

/** typedef **/

typedef long long LL;

/** Add - On **/

const int direct4[4][2]={ {0,1},{1,0},{0,-1},{-1,0} };
const int direct8[8][2]={ {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int direct3[6][3]={ {1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1} };

const int MOD = 1000000007;
const int INF = 0x3f3f3f3f;
const long long INFF = 1LL << 60;
const double EPS = 1e-9;
const double OO = 1e15;
const double PI = acos(-1.0); //M_PI;
const int maxn=111111;

int a[maxn];
int sum[maxn];
int que[maxn];
int head,tail;

int getin()
{
char ch=' ';
while (ch<'0'||ch>'9') ch=getchar();
int x=0;
while (ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x;
}

double getup(int i,int j)
{
return sum[i]-sum[j];
}
int getdown(int i,int j)
{
return i-j;
}
long long cross(int a,int b,int c)
{
long long x1=b-a;
long long y1=sum[b]-sum[a];
long long x2=c-b;
long long y2=sum[c]-sum[b];
return x1*y2-y1*x2;
}
int dbsearch(int l,int r,int i)
{
while (l<r)
{
int mid=(l+r)/2;
if (cross(que[mid],que[mid+1],i)<0) r=mid;
else l=mid+1;
}
return l;
}

int main()
{
int n,k;
while (~scanf("%d%d",&n,&k))
{
sum[0]=0;
REP_1(i,n)
{
a[i]=getin();
sum[i]=sum[i-1]+a[i];
}
head=tail=0;
que[tail++]=0;
double ans=0;
FOR_1(i,k,n)
{
int j=i-k;
while (head+1<tail&&cross(que[tail-2],que[tail-1],j)<0) tail--;
que[tail++]=j;
int tmp=dbsearch(0,tail-1,i);
double f=double(sum[i]-sum[que[tmp]])/(i-que[tmp]);
ans=max(ans,f);
}
printf("%0.2f\n",ans);
}
return 0;
}


Print
ArticleO(n)

/** head-file **/

#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <algorithm>

/** define-for **/

#define REP(i, n) for (int i=0;i<int(n);++i)
#define FOR(i, a, b) for (int i=int(a);i<int(b);++i)
#define DWN(i, b, a) for (int i=int(b-1);i>=int(a);--i)
#define REP_1(i, n) for (int i=1;i<=int(n);++i)
#define FOR_1(i, a, b) for (int i=int(a);i<=int(b);++i)
#define DWN_1(i, b, a) for (int i=int(b);i>=int(a);--i)
#define REP_N(i, n) for (i=0;i<int(n);++i)
#define FOR_N(i, a, b) for (i=int(a);i<int(b);++i)
#define DWN_N(i, b, a) for (i=int(b-1);i>=int(a);--i)
#define REP_1_N(i, n) for (i=1;i<=int(n);++i)
#define FOR_1_N(i, a, b) for (i=int(a);i<=int(b);++i)
#define DWN_1_N(i, b, a) for (i=int(b);i>=int(a);--i)

/** define-useful **/

#define clr(x,a) memset(x,a,sizeof(x))
#define sz(x) int(x.size())
#define see(x) cerr<<#x<<" "<<x<<endl
#define se(x) cerr<<" "<<x
#define pb push_back
#define mp make_pair

/** test **/

#define Display(A, n, m) {                      \
REP(i, n){                                  \
REP(j, m) cout << A[i][j] << " ";       \
cout << endl;                           \
}                                           \
}

#define Display_1(A, n, m) {                    \
REP_1(i, n){                                \
REP_1(j, m) cout << A[i][j] << " ";     \
cout << endl;                           \
}                                           \
}

using namespace std;

/** typedef **/

typedef long long LL;

/** Add - On **/

const int direct4[4][2]={ {0,1},{1,0},{0,-1},{-1,0} };
const int direct8[8][2]={ {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int direct3[6][3]={ {1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1} };

const int MOD = 1000000007;
const int INF = 0x3f3f3f3f;
const long long INFF = 1LL << 60;
const double EPS = 1e-9;
const double OO = 1e15;
const double PI = acos(-1.0); //M_PI;
/**
f[i]=min( f[j]+(sum[i]-sum[j])^2+M )
y为f[j]+sum[j]^2,x为2*sum[j],斜率为sum[i],截距为f[i]
**/
const int maxn=550000;
int n,m;
int a[maxn];
int f[maxn];
int que[maxn];
int head,tail;
int sum[maxn];
int gety(int j){return f[j]+sum[j]*sum[j];}
int getx(int j){return 2*sum[j];}
int dp_sol(int i,int j){return f[j]+(sum[i]-sum[j])*(sum[i]-sum[j])+m;}
bool cmp_idx(int i,int j,int k)
{
return (gety(i)-gety(j))*(getx(j)-getx(k))<=(gety(j)-gety(k))*(getx(i)-getx(j));
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
memset(f,0,sizeof(f));
sum[0]=0;
REP_1(i,n)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
head=tail=0;
que[tail++]=0;
f[0]=0;
for (int i=1;i<=n;i++)
{
while (tail-head>1&&dp_sol(i,que[head])>=dp_sol(i,que[head+1])) head++;
f[i]=dp_sol(i,que[head]);
while (tail-head>1&&cmp_idx(i,que[tail-1],que[tail-2])) tail--;
que[tail++]=i;
}
cout<<f
<<endl;
}
return 0;
}


其他题目

Codeforces
Round #189 (Div. 2) 解题报告

四、BST解决不单调的dp问题

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: