概述

动态$dp$是一类需要对$dp$的输入数据进行修改,并在修改后要快速查询的问题。

求解动态$dp$最基本的思路是分治。

一直在想动态$dp$是不是叫动态动态规划(误

例题

SPOJ 1716

 

从题目开始说起吧,这样会比较好说。

【学习笔记】动态dp

 

 

0

可以比较直观地看出线段树的做法。

每个节点,维护一个区间和,前缀最大和,后缀最大和,和最大子段和。

然后就可以单点修改,区间查询。

#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#include<cstdlib>
using namespace std;
#define N 500005
#define ll long long
#define INF 0x3f3f3f3f
struct node{
    int sum,ms/*maxsum*/,ml,mr/*maxl,maxr*/;
}tree[N*4];
int n,a[N];
inline int rd()
{
    int f=1,x=0;char c=getchar();
    while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
    while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return f*x;
}
void PushUp(int i)
{
    tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
    tree[i].ml=max(tree[i<<1].sum+tree[i<<1|1].ml,tree[i<<1].ml);
    tree[i].mr=max(tree[i<<1|1].sum+tree[i<<1].mr,tree[i<<1|1].mr);
    tree[i].ms=max(max(tree[i<<1].ms,tree[i<<1|1].ms),tree[i<<1].mr+tree[i<<1|1].ml);
}
void build(int i,int l,int r)
{
    if(l==r)
    {
        tree[i].sum=tree[i].ml=tree[i].mr=tree[i].ms=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    PushUp(i);
}
void update(int i,int pos,int val,int l,int r)
{
    if(l==r)
    {
        tree[i].ms=tree[i].ml=tree[i].mr=tree[i].sum=val;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)
        update(i<<1,pos,val,l,mid);
    else update(i<<1|1,pos,val,mid+1,r);
    PushUp(i);
}
node query(int i,int li,int ri,int l,int r)
{
    if(l<=li&&ri<=r)
        return tree[i];
    int mid=(li+ri)>>1;
    if(r<=mid) return query(i<<1,li,mid,l,r);
    else if(l>mid) return query(i<<1|1,mid+1,ri,l,r);
    else
    {
        node x=query(i<<1,li,mid,l,r),y=query(i<<1|1,mid+1,ri,l,r),res;
        res.sum=x.sum+y.sum;
        res.ml=max(x.sum+y.ml,x.ml);
        res.mr=max(y.sum+x.mr,y.mr);
        res.ms=max(max(x.ms,y.ms),x.mr+y.ml);
        return res;
    }
}
int main()
{
    n=rd(); 
    for(int i=1;i<=n;i++)
        a[i]=rd();
    build(1,1,n);
    int Q=rd();
    while(Q--)
    {
        int opt=rd();
        if(opt==1)
        {
            int x=rd(),y=rd(),tmp;
            if(x>y) tmp=x,x=y,y=tmp;
            printf("%d\n",query(1,1,n,x,y).ms);
        }
        else if(opt==0)
        {
            int x=rd(),y=rd();
            update(1,x,y,1,n); 
        }
    }
    return 0;
}
View Code

相关文章: