题目
思路
使用带Lazy的平衡树,无旋Treap
详见注释
Code:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXM 15
#define MAXN 500005
#define LL long long
#define Int register int
#define Int_Max 2147483647
using namespace std;
inline void read(int &x)
{
x = 0;
int f = 1;
char s = getchar();
while (s < '0' || s > '9')
{
if (s == '-')
f = -1;
s = getchar();
}
while (s >= '0' && s <= '9')
{
x = (x << 3) + (x << 1) + (s ^ 48);
s = getchar();
}
x *= f;
}
int Root, Num, a[MAXN], Sta[MAXN], Index_Sta;
struct node
{
int l, r, Size, val, Cov, Xiu;
bool Lazy, CovLazy;
int Sum, Maxqj, MaxPre, MaxBac;
}Point[MAXN];
inline int Max(int x,int y)
{
return x > y ? x : y;
}
inline int Min(int x,int y)
{
return x < y ? x : y;
}
int GetHash()
{
static int Seed = 252006;
Seed = (int)Seed * 121725 % Int_Max;
return Seed;
}
int NewNode(int v)
{
Num = Sta[Index_Sta --];
Point[Num].Size = 1;
Point[Num].Xiu = GetHash();
Point[Num].Maxqj = Point[Num].val = Point[Num].Sum = v;
Point[Num].MaxPre = Point[Num].MaxBac = Max(0, v); //维护最大前缀和和最大后缀和
Point[Num].l = Point[Num].r = Point[Num].Cov = Point[Num].Lazy = Point[Num].CovLazy = 0;
return Num;
}
void Push_Up(int x)
{
if (! x)
return ;
Point[x].Size = Point[Point[x].l].Size + Point[Point[x].r].Size + 1; // 左加右加自己
Point[x].Sum = Point[Point[x].l].Sum + Point[Point[x].r].Sum + Point[x].val; // 左加右加自己
Point[x].MaxPre = Max(Point[Point[x].l].MaxPre, Point[Point[x].l].Sum + Point[x].val + Point[Point[x].r].MaxPre); // 维护最大前缀和
Point[x].MaxBac = Max(Point[Point[x].r].MaxBac, Point[Point[x].r].Sum + Point[x].val + Point[Point[x].l].MaxBac); // 维护最大后缀和
Point[x].Maxqj = Max(Point[x].val, Point[x].val + Point[Point[x].l].MaxBac + Point[Point[x].r].MaxPre); // 维护最大区间和
if (Point[x].l)
Point[x].Maxqj = Max(Point[x].Maxqj, Point[Point[x].l].Maxqj);
if (Point[x].r)
Point[x].Maxqj = Max(Point[x].Maxqj, Point[Point[x].r].Maxqj);
/*如果有左/右儿子,有可能是左/右儿子的最大区间和*/
}
void Swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
void Reverse(int x)
{
if (! x)
return ;
Swap(Point[x].l, Point[x].r);
Swap(Point[x].MaxPre, Point[x].MaxBac); // 交换左右儿子的同时也要交换最大前缀和 & 后缀和
Point[x].Lazy = ! Point[x].Lazy;
}
void Cover(int x,int c)
{
Point[x].val = Point[x].Cov = c;
Point[x].Sum = Point[x].Size * c;
Point[x].CovLazy = 1;
Point[x].MaxPre = Point[x].MaxBac = Max(0, Point[x].Sum);
Point[x].Maxqj = Max(c, Point[x].Sum);
}
void Push_down(int x)
{
if (! x)
return ;
if (Point[x].Lazy)
{
if (Point[x].l)
Reverse(Point[x].l);
if (Point[x].r)
Reverse(Point[x].r);
Point[x].Lazy = 0;
}
if (Point[x].CovLazy)
{
if (Point[x].l)
Cover(Point[x].l, Point[x].Cov);
if (Point[x].r)
Cover(Point[x].r, Point[x].Cov);
Point[x].Cov = Point[x].CovLazy = 0;
}
}
void Delete(int x)
{
if (! x)
return ;
Sta[++ Index_Sta] = x;
if (Point[x].l)
Delete(Point[x].l);
if (Point[x].r)
Delete(Point[x].r);
}
void Split(int x,int &u,int &v,int k) // 按 Rank Split
{
if ( x )
Push_down( x );
if (! x)
{
u = v = 0;
return ;
}
if (Point[Point[x].l].Size < k) // 左儿子小于 k
{
u = x;
Split(Point[x].r, Point[u].r, v, k - Point[Point[x].l].Size - 1); // 拆右子树
}
else
{
v = x;
Split(Point[x].l, u, Point[v].l, k); // 拆左子树
}
Push_Up( x );
}
void Merge(int u,int v,int &x)
{
if (! u || ! v)
{
x = u | v;
return ;
}
if (Point[u].Xiu < Point[v].Xiu)
{
Push_down( u );
x = u;
Merge(Point[u].r, v, Point[x].r); // 并上右子树
Push_Up( u );
}
else
{
Push_down( v );
x = v;
Merge(u, Point[v].l, Point[x].l); // 并上左子树
Push_Up( v );
}
}
int Build(int l,int r)
{
int x, Mid = (l + r) / 2;
if (l == r)
return NewNode( a[Mid] );
Merge(Build(l, Mid), Build(Mid + 1, r), x);
return x;
}
int main()
{
srand(*new unsigned);
int n, m;
read( n ); read( m );
for (Int i = 1; i <= MAXN - 5; ++ i)
Sta[++ Index_Sta] = i;
for (Int i = 1; i <= n; ++ i)
read( a[i] );
Merge(Root, Build(1, n), Root);
while (m --)
{
char Or[MAXM];
scanf("%s", Or);
switch ( Or[2] )
{
case 'S':
{
int pos, tot;
read( pos ); read( tot );
int x, y;
Split(Root, x, y, pos); // 按 pos 拆成两半
for (Int i = 1; i <= tot; ++ i)
read( a[i] );
Merge(x, Build(1, tot), x); // 并入前一半
Merge(x, y, Root); // 并入后一半
break;
}
case 'L':
{
int pos, tot;
read( pos ); read( tot );
int x, y, z;
Split(Root, x, y, pos - 1);
Split(y, y, z, tot);
Delete( y );
Merge(x, z, Root);
break;
}
case 'K':
{
int pos, tot, c;
read( pos ); read( tot ); read( c );
int x, y, z;
Split(Root, x, y, pos - 1);
Split(y, y, z, tot);
Cover(y, c);
Merge(x, y, x);
Merge(x, z, Root);
break;
}
case 'V':
{
int pos, tot;
read( pos ); read( tot );
int x, y, z;
Split(Root, x, y, pos - 1);
Split(y, y, z, tot);
Reverse( y );
Merge(x, y, y);
Merge(y, z, Root);
break;
}
case 'T':
{
int pos, tot;
read( pos ); read( tot );
int x, y, z;
Split(Root, x, y, pos - 1);
Split(y, y, z, tot);
printf("%d\n", Point[y].Sum);
Merge(x, y, y);
Merge(y, z, Root);
break;
}
case 'X':
{
printf("%d\n", Point[Root].Maxqj);
break;
}
}
}
return 0;
}