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

来源:互联网 发布:gta4渣优化 编辑:程序博客网 时间:2024/05/22 05:09


一、单调队列

志愿者选拔 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[n]<<endl;    }    return 0;}


其他题目

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



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






原创粉丝点击