HDU 3698 Let the light guide us dp+线段树维护区间极值

来源:互联网 发布:vscode 代码片段 编辑:程序博客网 时间:2024/05/22 12:23

很简单的dp 线段树维护区间最小值 第一题线段树 留个纪念

#include <cstdio>#include <algorithm>using namespace std;const int inf=0x3f3f3f3f;int n,m,T[105][5005],f[105][5005],dp[5005],t[5005];struct s {    int l,r,val,lazy;    void upd(int v) {        val=min(val,v);        lazy=min(lazy,v);    }} seg[5005<<2];void pup(int x) {    seg[x].val=min(seg[x<<1].val,seg[x<<1|1].val);}void init(int x,int l,int r) {    seg[x].l=l,seg[x].r=r;    seg[x].val=seg[x].lazy=inf;    if (l==r)        return;    int m=(l+r)>>1;    init(x<<1,l,m);    init(x<<1|1,m+1,r);    pup(x);}void pdown(int x) {    int lv=seg[x].lazy;    if (lv!=inf) {        seg[x].lazy=inf;        seg[x<<1].upd(lv);        seg[x<<1|1].upd(lv);    }}void upd(int x,int l,int r,int v) {    int L=seg[x].l,R=seg[x].r;    if (l<=L&&r>=R) {        seg[x].upd(v);        return;    }    pdown(x);    int m=(L+R)>>1;    if (m>=l)        upd(x<<1,l,r,v);    if (m<r)        upd(x<<1|1,l,r,v);    pup(x);}int qry(int x,int l,int r) {    int L=seg[x].l,R=seg[x].r;    if (l<=L&&r>=R)        return seg[x].val;    pdown(x);    int m=(L+R)>>1,ret=inf;    if (m>=l)        ret=min(ret,qry(x<<1,l,r));    if (m<r)        ret=min(ret,qry(x<<1|1,l,r));    pup(x);    return ret;}int main(){    while (scanf("%d%d",&n,&m)==2&&n+m) {        for (int i=1;i<=n;++i)            for (int j=1;j<=m;++j)                scanf("%d",&T[i][j]);        for (int i=1;i<=n;++i)            for (int j=1;j<=m;++j)                scanf("%d",&f[i][j]);        init(1,1,m);        for (int i=1;i<=m;++i)            upd(1,max(1,i-f[1][i]),min(m,i+f[1][i]),T[1][i]);        for (int i=2;i<=n;++i) {            for (int j=1;j<=m;++j)                t[j]=qry(1,max(1,j-f[i][j]),min(m,j+f[i][j]))+T[i][j];            init(1,1,m);            for (int j=1;j<=m;++j)                upd(1,max(1,j-f[i][j]),min(m,j+f[i][j]),t[j]);        }        printf("%d\n",qry(1,1,m));    }    return 0;}


1 0