Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
9 8 2 -6 3 5 1 -5 -3 6 3 GET-SUM 5 4 MAX-SUM INSERT 8 3 -5 7 2 DELETE 12 1 MAKE-SAME 3 3 2 REVERSE 3 6 GET-SUM 5 4 MAX-SUM
Sample Output
-1 10 1 10
Hint
作为splay的终极boss,此题真的是聚集了splay的各种操作啊,简直可怕。
还好,只要掌握了splay的精髓,一样可以解决,此题要注意数组的大小,开50w就好了
一开始开的400w提交竟然说超时。。前后加上点防止越界,询问注意区间就好了。
关于最大连续子序列,只要像线段树那样维护就好了。加上读入挂可以优化1s左右。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<functional>
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int maxn = 1e6;
int n, m, root, a[maxn], l, r, c;
char s[20];
void Scan(int &x)
{
int flag = 1, res = 0; char ch;
while (((ch = getchar()) > '9' || ch < '0') && ch != '-');
if (ch == '-') flag = -1; else res = ch - '0';
while ((ch = getchar()) <= '9'&&ch >= '0') res = res * 10 + ch - '0';
x = flag*res;
}
struct Splays
{
const static int maxn = 5e5 + 10; //节点个数
const static int INF = 0x7FFFFFFF; //int最大值
int ch[maxn][2], F[maxn], sz; //左右儿子,父亲节点和节点总个数
int C[maxn], S[maxn], A[maxn], G[maxn], L[maxn], R[maxn], M[maxn], K[maxn];
queue<int> p;
int Node(int f, int a) {
sz = p.front(); p.pop();
L[sz] = R[sz] = S[sz] = A[sz] = a; C[sz] = 1; K[sz] = G[sz] = ch[sz][0] = ch[sz][1] = 0; F[sz] = f;
return sz;
}//申请一个新节点
void clear()
{
while (!p.empty()) p.pop();
for (int i = 1; i < maxn; i++) p.push(i);
ch[0][0] = ch[0][1] = F[0] = 0;
G[0] = K[0] = S[0] = C[0] = 0;
L[0] = R[0] = M[0] = -INF;
}//清空操作
void pushdown(int x)
{
if (G[x])
{
G[ch[x][0]] ^= 1; swap(L[ch[x][0]], R[ch[x][0]]);
G[ch[x][1]] ^= 1; swap(L[ch[x][1]], R[ch[x][1]]);
G[x] ^= 1; swap(ch[x][0], ch[x][1]);
}
if (K[x])
{
K[ch[x][0]] = K[ch[x][1]] = K[x];
if (ch[x][0])
{
A[ch[x][0]] = A[x];
S[ch[x][0]] = A[x] * C[ch[x][0]];
L[ch[x][0]] = R[ch[x][0]] = M[ch[x][0]] = A[x] > 0 ? S[ch[x][0]] : A[x];
}
if (ch[x][1])
{
A[ch[x][1]] = A[x];
S[ch[x][1]] = A[x] * C[ch[x][1]];
L[ch[x][1]] = R[ch[x][1]] = M[ch[x][1]] = A[x] > 0 ? S[ch[x][1]] : A[x];
}
K[x] = 0;
}
}
void Count(int x)
{
L[x] = max(L[ch[x][0]], S[ch[x][0]] + A[x] + max(0, L[ch[x][1]]));
R[x] = max(R[ch[x][1]], S[ch[x][1]] + A[x] + max(0, R[ch[x][0]]));
M[x] = max(0, R[ch[x][0]]) + A[x] + max(0, L[ch[x][1]]);
M[x] = max(M[x], max(M[ch[x][0]], M[ch[x][1]]));
C[x] = C[ch[x][0]] + C[ch[x][1]] + 1;
S[x] = S[ch[x][0]] + S[ch[x][1]] + A[x];
}
void rotate(int x, int k)
{
int y = F[x]; ch[y][!k] = ch[x][k]; F[ch[x][k]] = y;
if (F[y]) ch[F[y]][y == ch[F[y]][1]] = x;
F[x] = F[y]; F[y] = x; ch[x][k] = y;
L[x] = L[y]; R[x] = R[y]; M[x] = M[y];
C[x] = C[y]; S[x] = S[y]; Count(y);
}
void Splay(int x, int r)
{
for (int fa = F[r]; F[x] != fa;)
{
if (F[F[x]] == fa) { rotate(x, x == ch[F[x]][0]); return; }
int y = x == ch[F[x]][0], z = F[x] == ch[F[F[x]]][0];
y^z ? (rotate(x, y), rotate(x, z)) : (rotate(F[x], z), rotate(x, y));
}
}
void build(int fa, int&x, int l, int r)
{
if (l > r) return;
int mid = l + r >> 1;
x = Node(fa, a[mid]);
build(x, ch[x][0], l, mid - 1);
build(x, ch[x][1], mid + 1, r);
Count(x);
}
void find(int &x, int k)
{
for (int i = x; i;)
{
pushdown(i);
if (k < C[ch[i][0]]) { i = ch[i][0]; continue; }
if (k == C[ch[i][0]]) { Splay(i, x); x = i; break; }
k -= C[ch[i][0]] + 1; i = ch[i][1];
}
}
void Insert(int &x)
{
Scan(l); Scan(r);
for (int i = 1; i <= r; i++) Scan(a[i]);
int root; build(0, root, 1, r);
find(x, l); find(ch[x][1], 0);
ch[ch[x][1]][0] = root; F[root] = ch[x][1];
Count(ch[x][1]); Count(x);
}
void earse(int x)
{
if (!x) return;
p.push(x);
earse(ch[x][0]);
earse(ch[x][1]);
}
void Delete(int &x)
{
Scan(l); Scan(r); l--;
find(x, l); find(ch[x][1], r);
earse(ch[ch[x][1]][0]);
ch[ch[x][1]][0] = 0;
Count(ch[x][1]); Count(x);
}
void MakeSa(int &x)
{
Scan(l); Scan(r); Scan(c); l--;
find(x, l); find(ch[x][1], r);
int g = ch[ch[x][1]][0];
A[g] = c; S[g] = c*C[g]; K[g] = 1;
L[g] = R[g] = M[g] = c > 0 ? S[g] : c;
Count(ch[x][1]); Count(x);
}
void Rotate(int &x)
{
Scan(l); Scan(r); l--;
find(x, l); find(ch[x][1], r);
int g = ch[ch[x][1]][0]; G[g] ^= 1;
swap(L[g], R[g]);
Count(ch[x][1]); Count(x);
}
void GetSum(int &x)
{
Scan(l); Scan(r); l--;
find(x, l); find(ch[x][1], r);
printf("%d\n", S[ch[ch[x][1]][0]]);
}
void MaxSum(int &x)
{
find(x, 0); find(ch[x][1], maxn - 3 - p.size());
printf("%d\n", M[ch[ch[x][1]][0]]);
}
}solve;
int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
a[0] = a[n + 1] = root = 0;
solve.clear();
for (int i = 1; i <= n; i++) Scan(a[i]);
solve.build(0, root, 0, n + 1);
while (m--)
{
scanf("%s", s);
if (s[2] == 'S') solve.Insert(root);
if (s[2] == 'L') solve.Delete(root);
if (s[2] == 'K') solve.MakeSa(root);
if (s[2] == 'V') solve.Rotate(root);
if (s[2] == 'T') solve.GetSum(root);
if (s[2] == 'X') solve.MaxSum(root);
}
}
return 0;
}