1. 程式人生 > 其它 >CF722C Destroying Array 題解

CF722C Destroying Array 題解

根據目前作者瞭解,本題有兩種解法:並查集/線段樹。

1. 並查集

對於並查集這種只能合併不能刪除的資料結構,當然要想一點珂技。

我們倒過來思考,將刪除操作變為插入操作,相鄰點合併。

考慮到序列裡面的數都為正數,那麼直接取出子樹權值和最大的即可。

預計時間複雜度 \(O(n)\),上界 \(O(n \log n)\)

2. 線段樹

這個需要模仿 GSS 系列,維護字首和,字尾和,總和,最大子段和,然後刪除操作處理成最小值。這個方法支援數為負數的情況。

沒了解過 GSS 系列的讀者可以看一看這篇文章:線段樹演算法總結&專題訓練3

時間複雜度 \(O(n \log n)\),上下界也為 \(O(n \log n)\)

程式碼:(只有線段樹)

#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;
}