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\n",dp[n]); return 0; }