現在の著者の理解によると、この問題には2つの解決策があります。ユニオン検索/線分ツリーです。
1.組み合わせる
もちろん、ユニオン検索セットのように、マージのみが可能で削除できないデータ構造については、いくつかのスキルを考慮する必要があります。
逆に考えてみましょう。削除操作を挿入操作に変えて、隣接するポイントをマージします。
シーケンス内の数値がすべて正であることを考慮して、サブツリーの重みと最大の重みを取り出します。
推定時間計算量O(n)O(n)O (n )、上界と下界O(nlogn)O(n \ log n)O (nlo gn )。
2.線分ツリー
これは、GSSシリーズを模倣し、プレフィックス合計、サフィックス合計、合計合計、最大サブセグメント合計を維持してから、操作を最小値まで削除する必要があります。このメソッドは負の数をサポートします。
GSSシリーズを知らない読者は、この記事を見ることができます:線分ツリーアルゴリズムの概要と特別なトレーニング3
時間計算量O(nlogn)O(n \ log n)O (nlo gn )、上限と下限もO(nlogn)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;
}