欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

动态dp

程序员文章站 2022-07-12 09:10:09
...
/*
动态dp,支持修改操作的dp最大值最小值维护
定义广义矩阵乘法
c[i][j]=max(a[i][k]+b[k][j])  加法对min与max有结合律 
对于转移g[i]=max(g[i-1],f[i]),f[i]=max(f[i-1]+a[i],a[i])
尝试构造矩阵,利用线段树来维护区间的广义矩阵乘法的值,这样就能算区间的dp值 
*/

#include <iostream>
#include <cstring>
using namespace std;

typedef long long ll;

const int maxn = 5e4 + 5;

struct Matrix{
	ll data[4][4];
	Matrix operator*(const Matrix&n)const    //重载矩阵乘法 
	{
		Matrix tmp;
		for (int i = 1; i <= 3; i++)
			for (int j = 1; j <= 3; j++) tmp.data[i][j] = -1e18;
		for (int i = 1; i <= 3; i++)
		{
			for (int j = 1; j <= 3; j++)
			{
				for (int k = 1; k <= 3; k++)
					tmp.data[i][j] = max(tmp.data[i][j],data[i][k]+n.data[k][j]);
			}
		}
		return tmp;
	}
};

struct node{
	int l,r;
	Matrix m;
}a[maxn*4]; 

int p[maxn];

void update(int x)
{
	a[x].m = a[2*x].m * a[2*x+1].m;
}

void build(int x,int l,int r)
{
	a[x].l = l,a[x].r = r;
	if( l == r )   //构造单点的矩阵 
	{
		a[x].m.data[1][1] = a[x].m.data[1][3] = a[x].m.data[2][1] = a[x].m.data[2][3] = p[l];
		a[x].m.data[1][2] = a[x].m.data[3][2] = a[x].m.data[3][1] = -1e18;
		a[x].m.data[2][2] = a[x].m.data[3][3] = 0;
		return;
	}
	int m = (l+r) >> 1;
	build(2*x,l,m),build(2*x+1,m+1,r);
	update(x);
}

void modify(int x,int p,int v)   //修改单点的矩阵 
{
	if( a[x].l == a[x].r )
	{
		a[x].m.data[1][1] = a[x].m.data[1][3] = a[x].m.data[2][1] = a[x].m.data[2][3] = v;
		return;
	}
	int m = (a[x].l + a[x].r) >> 1;
	if( p <= m ) modify(2*x,p,v);
	else modify(2*x+1,p,v);
	update(x);
}

Matrix query(int x,int l,int r)   //查询区间的矩阵广义乘 
{
	if( a[x].l == l && a[x].r == r ) return a[x].m;
	int m = (a[x].l+a[x].r) >> 1; 
	if( l > m ) return query(2*x+1,l,r);
	else if( r <= m ) return query(2*x,l,r);
	else return query(2*x,l,m) * query(2*x+1,m+1,r);
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> p[i];
	build(1,1,n);
	int q;
	cin >> q;
	while( q-- )
	{
		int op,x,y;
		cin >> op >> x >> y;
		if( op == 1 )
		{
			Matrix ans; 
			if( x > y ) swap(x,y);
			ans = query(1,x,y);
			cout << ans.data[2][3] << '\n';
		}else modify(1,x,y); 
	}
	return 0;
}

相关标签: 动态规划