码迷,mamicode.com
首页 > 其他好文 > 详细

Bzoj1496: [NOI2006]千年虫

时间:2018-04-03 21:59:04      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:math   long   span   namespace   har   ref   ++   +=   长度   

题面

传送门

Sol

左右可以分开搞
然后就是要形成一个类似梳子的东西
\(f[0/1][i][j]\)
\(0\)凹,\(1\)凸,\(i\)为行,可以滚一维,\(j\)为该行长度
\(f[0][i][j] = min(f[0][i - 1][j], f[1][i - 1][k]) + j - a[i]; k > j\)
\(f[1][i][j] = min(f[1][i - 1][j], f[0][i - 1][k]) + j - a[i]; k < j\)

然后是\(O(n^3)\)优化可以变成\(O(n^2)\)
可以有\(50\)

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF(1e9);
const int _(1e6 + 5);
typedef long long ll;

IL int Input(){
    RG int x = 0, z = 1; RG char c = getchar();
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x * z;
}

int n, l[_], r[_], ans, f[2][2][_], MX;

IL int Solve(){
    Fill(f, 63);
    for(RG int i = r[1]; i <= MX; ++i) f[0][1][i] = i - r[1];
    for(RG int i = 2; i <= n; ++i){
        RG int p = i & 1, q = p ^ 1;
        for(RG int j = 0; j < r[i]; ++j) f[0][p][j] = f[1][p][j] = INF;
        for(RG int j = MX, mn = INF; j >= r[i]; --j){
            f[0][p][j] = min(f[0][q][j], mn) + j - r[i];
            mn = min(mn, f[1][q][j]);
        }
        RG int mn = INF;
        for(RG int j = 0; j < r[i]; ++j) mn = min(mn, f[0][q][j]);
        for(RG int j = r[i]; j <= MX; ++j){
            f[1][p][j] = min(f[1][q][j], mn) + j - r[i];
            mn = min(mn, f[0][q][j]);
        }
    }
    RG int ret = INF;
    for(RG int i = r[n]; i <= MX; ++i) ret = min(ret, f[0][n & 1][i]);
    return ret;
}

int main(RG int argc, RG char* argv[]){
    n = Input();
    for(RG int i = 1; i <= n; ++i)
        l[i] = Input(), r[i] = Input(), MX = max(MX, r[i] + 1);
    ans += Solve();
    for(RG int i = 1; i <= n; ++i) r[i] = MX - l[i];
    printf("%d\n", ans + Solve());
    return 0;
}

正解有个结论,这一行的\(dp\)值只跟上下两行的长度有关
并且只能为所有的\([a[i], a[i]+2]\)的并
然后不会证明
看代码就会写了

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
const int INF(1e9);
const int _(1e6 + 5);
typedef long long ll;

IL int Input(){
    RG int x = 0, z = 1; RG char c = getchar();
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x * z;
}

int n, l[_], r[_], ans, f[2][2][_], MX, g[2][_], t[2];

IL int Solve(){
    Fill(f, 63), t[1] = 0; RG int rr = min(3, n);
    for(RG int i = 1; i <= rr; ++i)
        for(RG int j = r[i]; j <= r[i] + 2; ++j)
            if(j >= r[1]) g[1][++t[1]] = j;
    for(RG int i = 1; i <= t[1]; ++i) f[0][1][i] = g[1][i] - r[1];
    for(RG int i = 2; i <= n; ++i){
        RG int q = i & 1, p = q ^ 1; t[q] = 0;
        RG int ll = max(1, i - 2), rr = min(i + 2, n);
        for(RG int j = ll; j <= rr; ++j)
            for(RG int k = r[j]; k <= r[j] + 2; ++k)
                if(k >= r[i]) g[q][++t[q]] = k;
        for(RG int j = 1; j <= t[q]; ++j){
            f[0][q][j] = f[1][q][j] = INF;
            for(RG int k = 1; k <= t[p]; ++k){
                if(g[p][k] > g[q][j]) f[0][q][j] = min(f[0][q][j], f[1][p][k]);
                else if(g[p][k] < g[q][j]) f[1][q][j] = min(f[1][q][j], f[0][p][k]);
                else f[0][q][j] = min(f[0][q][j], f[0][p][k]), f[1][q][j] = min(f[1][q][j], f[1][p][k]);
            }
            f[0][q][j] += g[q][j] - r[i], f[1][q][j] += g[q][j] - r[i];
        }
    }
    RG int ret = INF, q = n & 1;
    for(RG int i = 1; i <= t[q]; ++i) ret = min(ret, f[0][q][i]);
    return ret;
}

int main(RG int argc, RG char* argv[]){
    freopen("worm.in", "r", stdin);
    freopen("worm.out", "w", stdout);
    n = Input();
    for(RG int i = 1; i <= n; ++i)
        l[i] = Input(), r[i] = Input(), MX = max(MX, r[i] + 1);
    ans += Solve();
    for(RG int i = 1; i <= n; ++i) r[i] = MX - l[i];
    printf("%d\n", ans + Solve());
    return 0;
}

Bzoj1496: [NOI2006]千年虫

标签:math   long   span   namespace   har   ref   ++   +=   长度   

原文地址:https://www.cnblogs.com/cjoieryl/p/8710996.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!