CF722C Destroying Array 题解

根据目前作者了解,本题有两种解法:并查集/线段树。

1. 并查集

对于并查集这种只能合并不能删除的数据结构,当然要想一点珂技。

我们倒过来思考,将删除操作变为插入操作,相邻点合并。

考虑到序列里面的数都为正数,那么直接取出子树权值和最大的即可。

预计时间复杂度 O ( n ) O(n) O(n),上界 O ( n log ⁡ n ) O(n \log n) O(nlogn)

2. 线段树

这个需要模仿 GSS 系列,维护前缀和,后缀和,总和,最大子段和,然后删除操作处理成最小值。这个方法支持数为负数的情况。

没了解过 GSS 系列的读者可以看一看这篇文章:线段树算法总结&专题训练3

时间复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn),上下界也为 O ( n log ⁡ n ) O(n \log n) O(nlogn)

代码:(只有线段树)

#include <bits/stdc++.h>
#define Max(a, b) ((a > b) ? a : b)
using namespace std;

typedef long long LL;
const int MAXN = 1e5 + 10;
const LL inf = -1e14;
int n, a[MAXN];
struct node
{
    
    
	int l, r, flag;
	LL sum, pre, aft, maxn;
	#define l(p) tree[p].l
	#define r(p) tree[p].r
	#define s(p) tree[p].sum
	#define p(p) tree[p].pre
	#define a(p) tree[p].aft
	#define m(p) tree[p].maxn
	node operator +(const node &fir)
	{
    
    
		node sec;
		sec.l = l; sec.r = fir.r;
		sec.sum = sum + fir.sum;
		sec.pre = Max(pre, sum + fir.pre);
		sec.aft = Max(fir.aft, fir.sum + aft);
		sec.maxn = Max(fir.maxn, Max(maxn, aft + fir.pre));
		sec.flag = flag | fir.flag;
		return sec;
	}
}tree[MAXN << 2];

int read()
{
    
    
	int sum = 0, fh = 1; char ch = getchar();
	while (ch < '0' || ch > '9') {
    
    if (ch == '-') fh = -1; ch = getchar();}
	while (ch >= '0' && ch <= '9') {
    
    sum = (sum << 3) + (sum << 1) + (ch ^ 48); ch = getchar();}
	return sum * fh;
}

void build(int p, int l, int r)
{
    
    
	l(p) = l, r(p) = r;
	if (l == r) {
    
    s(p) = a(p) = p(p) = m(p) = a[l]; tree[p].flag = 1; return ;}
	int mid = (l + r) >> 1;
	build (p << 1, l, mid); build(p << 1 | 1, mid + 1, r);
	tree[p] = tree[p << 1] + tree[p << 1 | 1];
}

void deal(int p, int x)
{
    
    
	if (l(p) == r(p) && r(p) == x)
	{
    
    
		tree[p].flag = 0;
		s(p) = m(p) = a(p) = p(p) = inf;
		return ;
	}
	int mid = (l(p) + r(p)) >> 1;
	if (x <= mid) deal(p << 1, x);
	else deal(p << 1 | 1, x);
	tree[p] = tree[p << 1] + tree[p << 1 | 1];
}

int main()
{
    
    
	n = read();
	for (int i = 1; i <= n; ++i) a[i] = read();
	build(1, 1, n);
	for (int i = 1; i <= n; ++i)
	{
    
    
		int x = read();
		deal(1, x);
		printf("%lld\n", Max(0ll, tree[1].maxn));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/BWzhuzehao/article/details/113766310