POJ 1769 Minimizing maximizer (线段树优化dp)

dp[i = 前i中sorter][j = 将min移动到j位置] = 最短的sorter序列。

对于sorteri只会更新它右边端点r的位置,因此可以把数组改成一维的,dp[r] = min(dp[r],dp[j]+1), l≤j<r。

不是滑窗,单调队列用用不了,但是可以用线段树去维护这个最小值。

/*********************************************************
*            ------------------                          *
*   author AbyssalFish                                   *
**********************************************************/
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
using namespace std;


#define para int o = 1, int l = 1,int r = n
#define TEMPvar int mid = (l+r)>>1, lc = (o<<1), rc = (o<<1|1);
#define lsn lc, l, mid
#define rsn rc, mid+1, r
#define insd ql<=l&&r<=qr
const int maxn = 5e4;
const int ST_SIZE = 1<<17;
const int INF = 0x3f3f3f3f;
int Min[ST_SIZE];
int n, m;
int dp[maxn+1];

void build(para)
{
    if(l == r){
        Min[o] = dp[l];
    }else {
        TEMPvar
        build(lsn);
        build(rsn);
        Min[o] = min(Min[lc],Min[rc]);
    }
}

int qpos,qval;
void update(para)
{
    if(l == r){
        Min[o] = qval;
    }else {
        TEMPvar
        if(qpos<=mid) update(lsn);
        else update(rsn);
        Min[o] = min(Min[lc],Min[rc]);
    }
}
int ql,qr;
int qMin(para)
{
    if(insd){ return Min[o]; }
    else {
        int res = INF;
        TEMPvar
        if(ql<=mid) res = min(res,qMin(lsn));
        if(qr>mid) res = min(res,qMin(rsn));
        return res;
    }
}



//#define LOCAL
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    scanf("%d%d",&n,&m);
    memset(dp+2,0x3f,sizeof(int)*(n-1));
    build();
    for(int i = 0; i < m; i++){
        scanf("%d%d",&ql,&qr);
        if((qval = qMin()+1) < dp[qr]){
            dp[qpos = qr] = qval;
            update();
        }
    }
    printf("%d
",dp[n]);
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4945650.html