树状数组维护前缀最大值

//https://codeforces.com/contest/1668/problem/D
#include<bits/stdc++.h>
#include<unordered_map>
//#define int ll
#define ll long long
#define ull unsigned long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;

const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;
const ll mod = 1e9 + 7;
const int N = 5e5 + 5;

int n, a[N], pre[N], dp[N], b[N];
map<ll, ll> id;

int lowbit(int x)
{
	return x & (-x);
}

void add(int x, int v)
{
	while (x < N)
	{
		b[x] = max(b[x], v);
		x += lowbit(x);
	}
}

int query(int x)
{
	int ans = -inf;
	while (x)
	{
		ans = max(ans, b[x]);
		x -= lowbit(x);
	}
	return ans;
}

void solve()
{
	cin >> n;
	for (int i = 0; i <= n; i++)
		b[i] = dp[i] = -inf;
	set<int> st;
	st.insert(0);
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		pre[i] = pre[i - 1] + a[i];
		st.insert(pre[i]);
	}
	int tot = 0;
	for (auto it : st)
		id[it] = ++tot;
	add(id[0], 0);
	dp[0] = 0;
	for (int i = 1; i <= n; i++)
	{
		if (a[i] < 0)
			dp[i] = dp[i - 1] - 1;
		else if (a[i] == 0)
			dp[i] = dp[i - 1];
		dp[i] = max(dp[i], query(id[pre[i]] - 1) + i);
		add(id[pre[i]], dp[i] - i);
	}
	cout << dp[n] << '\n';
}

signed main()
{
	IOS;
	int t = 1;
	cin >> t;
	while (t--)
		solve();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值