[Problem Description]
[Data Structure]
Splay
[Analysis]
Splay没话说,维护节点信息和pushdown,update与线段树有些像。
[Pay Attention]
这里有一个逗比的地方,MAX-SUM不包括空串这种情况,也就是说,就算序列里面最大的数是负数,也不能输出0,而是输出那个负数。
[Code]
/**************************************************************
Problem: 1500
User: gaotianyu1350
Language: C++
Result: Accepted
Time:4456 ms
Memory:42352 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <iostream>
using namespace std;
#define MAXN 700000
queue<int> pool;
struct splayNode
{
int ch[2];
int f;
int key, size, sum, lmax, rmax, mmax, doubi;
int flagSame, flagRe, nSame;
splayNode()
{
f = ch[0] = ch[1] = key = size = sum = lmax = rmax = mmax = 0;
flagSame = flagRe = nSame = 0;
doubi = 0;
}
void newNode(int father, int value)
{
f = father;
ch[0] = ch[1] = 0;
key = sum = value;
lmax = rmax = mmax = max(value, 0);
doubi = value;
size = 1;
flagSame = flagRe = nSame = 0;
}
void delNode()
{
f = 0;
ch[0] = ch[1] = key = size = sum = lmax = rmax = mmax = 0;
flagSame = flagRe = nSame = 0;
doubi = 0;
}
}s[MAXN];
int root;
int temp[MAXN], cnt;
inline void init()
{
while (!pool.empty()) pool.pop();
for (int i = 1; i < MAXN; i++)
pool.push(i);
root = 0;
}
inline int newNode(int father, int key)
{
int now = pool.front(); pool.pop();
s[now].newNode(father, key);
//if (father) s[father].ch[which] = now;
return now;
}
inline void delTree(int now)
{
queue<int> q;
while (!q.empty()) q.pop();
q.push(now);
while (!q.empty())
{
int now = q.front(); q.pop();
if (s[now].ch[0]) q.push(s[now].ch[0]);
if (s[now].ch[1]) q.push(s[now].ch[1]);
s[now].delNode();
pool.push(now);
}
}
inline void update(int now)
{
int left = s[now].ch[0], right = s[now].ch[1];
s[now].size = s[left].size + s[right].size + 1;
s[now].sum = s[left].sum + s[right].sum + s[now].key;
s[now].lmax = max(s[left].lmax, s[left].sum + s[now].key + s[right].lmax);
s[now].rmax = max(s[right].rmax, s[right].sum + s[now].key + s[left].rmax);
s[now].mmax = max(max(s[left].mmax, s[right].mmax), s[left].rmax + s[now].key + s[right].lmax);
s[now].doubi = s[now].key;
if (left) s[now].doubi = max(s[now].doubi, s[left].doubi);
if (right) s[now].doubi = max(s[now].doubi, s[right].doubi);
}
inline void Reverse(int now)
{
int temp = s[now].ch[0];
s[now].ch[0] = s[now].ch[1];
s[now].ch[1] = temp;
s[now].flagRe ^= 1;
temp = s[now].lmax;
s[now].lmax = s[now].rmax;
s[now].rmax = temp;
}
inline void Same(int now, int value)
{
s[now].key = s[now].nSame = value;
s[now].flagSame = 1;
s[now].sum = s[now].size * s[now].key;
s[now].lmax = s[now].rmax = s[now].mmax = s[now].sum > 0 ? s[now].sum : 0;
s[now].doubi = value;
}
inline void pushdown(int now)
{
int left = s[now].ch[0], right = s[now].ch[1];
if (s[now].flagSame)
{
if (left) Same(left, s[now].nSame);
if (right) Same(right, s[now].nSame);
s[now].flagSame = 0;
s[now].nSame = 0;
}
if (s[now].flagRe)
{
if (left) Reverse(left);
if (right) Reverse(right);
s[now].flagRe = 0;
}
}
inline int get(int now)
{
int father = s[now].f;
return now == s[father].ch[0] ? 0 : 1;
}
inline void rotate(int now)
{
int father = s[now].f, oldfather = s[father].f, which = get(now);
pushdown(father);
pushdown(now);
s[father].ch[which] = s[now].ch[which ^ 1];
s[s[father].ch[which]].f = father;
s[now].ch[which ^ 1] = father;
s[father].f = now;
s[now].f = oldfather;
if (oldfather)
s[oldfather].ch[s[oldfather].ch[0] == father ? 0 : 1] = now;
update(father);
update(now);
//if (oldfather) update(oldfather);
}
inline void splay(int now, int tar)
{
for (int father = s[now].f; father != tar; rotate(now), father = s[now].f)
if (s[father].f != tar)
get(now) == get(father) ? rotate(father) : rotate(now);
if (tar == 0)
root = now;
}
inline int find(int location)
{
int now = root;
while (now)
{
pushdown(now);
if (location == s[s[now].ch[0]].size + 1)
return now;
if (location <= s[s[now].ch[0]].size)
now = s[now].ch[0];
else
location -= s[s[now].ch[0]].size + 1, now = s[now].ch[1];
}
return -1000000000;
}
inline int build(int father, int left, int right)
{
if (left > right) return 0;
int mid = (left + right) >> 1;
int now = newNode(father, temp[mid]);
s[now].ch[0] = build(now, left, mid - 1);
s[now].ch[1] = build(now, mid + 1, right);
update(now);
return now;
}
inline void add(int pos)
{
int nleft = find(pos), nright = find(pos + 1);
splay(nleft, 0);
splay(nright, root);
if (s[nright].ch[0]) printf("Wrong at 186\n");
s[nright].ch[0] = build(nright, 1, cnt);
update(nright);update(root);
}
inline void del(int pos, int tot)
{
int nleft = find(pos - 1), nright = find(pos + tot);
splay(nleft, 0);
splay(nright, root);
if (!s[nright].ch[0]) printf("Wrong at 190\n");
else
{
delTree(s[nright].ch[0]);
s[nright].ch[0] = 0;
update(nright);update(root);
}
}
inline void makesame(int pos, int tot, int value)
{
int nleft = find(pos - 1), nright = find(pos + tot);
splay(nleft, 0);
splay(nright, root);
if (!s[nright].ch[0]) printf("Wrong at 203\n");
else
{
int now = s[nright].ch[0];
Same(now, value);
update(nright);update(root);
}
}
inline void makereverse(int pos, int tot)
{
int nleft = find(pos - 1), nright = find(pos + tot);
splay(nleft, 0);
splay(nright, root);
if (!s[nright].ch[0]) printf("Wrong at 218\n");
else
{
int now = s[nright].ch[0];
Reverse(now);
update(nright);update(root);
}
}
inline int getSum(int pos, int tot)
{
int nleft = find(pos - 1), nright = find(pos + tot);
if (tot == 0) return 0;
splay(nleft, 0);
splay(nright, root);
if (!s[nright].ch[0]) {printf("Wrong at 232\n");return -233;}
else
{
int now = s[nright].ch[0];
return s[now].sum;
}
}
inline int getMax()
{
if (s[root].doubi <= 0)
return s[root].doubi;
else
return s[root].mmax;
}
inline int quickread()
{
int ans = 0;
char c;
bool fu = false;
c = getchar();
while (!(('0' <= c && c <= '9') || c == '-'))
c = getchar();
if (c == '-')
{
fu = true;
c = getchar();
}
while ('0' <= c && c <= '9')
{
ans = ans * 10 + c - '0';
c = getchar();
}
return fu ? - ans : ans;
}
int main()
{
//freopen("input2.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
init();
temp[1] = temp[2] = -1000000000;
root = build(0, 1, 2);
int m;
char order[15];
cnt = quickread();
m = quickread();
for (int i = 1; i <= cnt; i++)
temp[i] = quickread();
add(1);
while (m--)
{
scanf(" %s", order);
int pos, value;
switch (order[0])
{
case 'I':
int pos;
pos = quickread();
cnt = quickread();
for (int i = 1; i <= cnt; i++)
temp[i] = quickread();
add(pos + 1);
break;
case 'D':
pos = quickread();
cnt = quickread();
del(pos + 1, cnt);
break;
case 'M':
if (order[2] == 'K')
{
pos = quickread();
cnt = quickread();
value = quickread();
makesame(pos + 1, cnt, value);
break;
}
else
{
printf("%d\n", getMax());
break;
}
case 'R':
pos = quickread();
cnt = quickread();
makereverse(pos + 1, cnt);
break;
case 'G':
pos = quickread();
cnt = quickread();
printf("%d\n", getSum(pos + 1, cnt));
break;
}
}
}