DDP 求调
查看原帖
DDP 求调
183603
SUNCHAOYI废物生成器楼主2025/1/8 17:59

和第二篇题解相似,不过不是很理解区间更新是为什么在负无穷对应的位置进行了 +2k+2k2k-2k 的操作。

我的代码并没有加上这个操作,然后样例均过,交上去 00 分。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define init(x) memset (x,-INF,sizeof (x))
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int MAX = 2e5 + 5;
const int MOD = 1e9 + 7;
inline int read ();
int n,q,a[MAX];ll tmp[MAX << 2];
struct Mat
{
	ll a[3][3];
	Mat ()
	{
		for (int i = 0;i < 3;++i)
			for (int j = 0;j < 3;++j) a[i][j] = 0;
	}
} tree[MAX << 2];
/*
f[i][0/1] 剩余最小/大值 f[i][2] 均已经匹配 
f[i][0] = max (f[i - 1][0],f[i - 1][2] + a[i])
f[i][1] = max (f[i - 1][1],f[i - 1][2] - a[i])
f[i][2] = max (f[i - 1][2],f[i - 1][0] - a[i],f[i - 1][1] + a[i])
*/
Mat operator * (Mat A,Mat B);
void build (int cur,int l,int r);
void modify (int cur,int l,int r,int x,int y,int v);
void pushdown (int cur);
void upd (int cur,ll v);
int main ()
{
	//freopen (".in","r",stdin);
	//freopen (".out","w",stdout);
	n = read ();q = read ();
	for (int i = 1;i <= n;++i) a[i] = read ();
	build (1,1,n);
	while (q--)
	{
		int l = read (),r = read (),v = read ();
		modify (1,1,n,l,r,v);
		Mat ans;ans.a[0][0] = ans.a[1][0] = -INF;
		ans = tree[1] * ans;
		printf ("%lld\n",ans.a[2][0]);
	}
	return 0;
}
inline int read ()
{
    int s = 0;int f = 1;
    char ch = getchar ();
    while ((ch < '0' || ch > '9') && ch != EOF)
	{
        if (ch == '-') f = -1;
        ch = getchar ();
    }
    while (ch >= '0' && ch <= '9')
	{
        s = s * 10 + ch - '0';
        ch = getchar ();
    }
    return s * f;
}
Mat operator * (Mat A,Mat B)
{
	Mat C;
	for (int i = 0;i < 3;++i)
		for (int j = 0;j < 3;++j) C.a[i][j] = -INF;
	for (int i = 0;i < 3;++i)
		for (int j = 0;j < 3;++j)
			for (int k = 0;k < 3;++k) C.a[i][j] = max (C.a[i][j],A.a[i][k] + B.a[k][j]);
	return C;
}
void build (int cur,int l,int r)
{
	if (l == r)
	{
		upd (cur,a[l]);
		tree[cur].a[0][1] = tree[cur].a[1][0] = -INF;
		return ;
	}
	int mid = (l + r) >> 1;
	build (cur << 1,l,mid);build (cur << 1 | 1,mid + 1,r);
	tree[cur] = tree[cur << 1 | 1] * tree[cur << 1];
}
void upd (int cur,ll v)
{
	tree[cur].a[0][2] += v,tree[cur].a[2][1] += v;
	tree[cur].a[1][2] -= v,tree[cur].a[2][0] -= v;
}
void pushdown (int cur)
{
	if (!tmp[cur]) return ;
	upd (cur << 1,tmp[cur]);upd (cur << 1 | 1,tmp[cur]);
	tmp[cur << 1] += tmp[cur];tmp[cur << 1 | 1] += tmp[cur];
	tmp[cur] = 0;
}
void modify (int cur,int l,int r,int x,int y,int v)
{
	if (x <= l && y >= r)
	{
		upd (cur,v);tmp[cur] += v;
		return ;
	}
	int mid = (l + r) >> 1;
	pushdown (cur);
	if (x <= mid) modify (cur << 1,l,mid,x,y,v);
	if (y > mid) modify (cur << 1 | 1,mid + 1,r,x,y,v);
	tree[cur] = tree[cur << 1 | 1] * tree[cur << 1];
}
2025/1/8 17:59
加载中...