CF722Cアレイの破壊题解

現在の著者の理解によると、この問題には2つの解決策があります。ユニオン検索/線分ツリーです。

1.組み合わせる

もちろん、ユニオン検索セットのように、マージのみが可能で削除できないデータ構造については、いくつかのスキルを考慮する必要があります。

逆に考えてみましょう。削除操作を挿入操作に変えて、隣接するポイントをマージします。

シーケンス内の数値がすべて正であることを考慮して、サブツリーの重みと最大の重みを取り出します。

推定時間計算量O(n)O(n)O n 、上界と下界O(nlog⁡n)O(n \ log n)O nlo gn

2.線分ツリー

これは、GSSシリーズを模倣し、プレフィックス合計、サフィックス合計、合計合計、最大サブセグメント合計を維持してから、操作を最小値まで削除する必要があります。このメソッドは負の数をサポートします。

GSSシリーズを知らない読者は、この記事を見ることができます:線分ツリーアルゴリズムの概要と特別なトレーニング3

時間計算量O(nlog⁡n)O(n \ log n)O nlo gn 、上限と下限もO(nlog⁡n)O(n \ log n)O nlo gn

コード:(線分ツリーのみ)

#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