/
example3.cpp
158 lines (146 loc) · 4.21 KB
/
example3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Solucion para
// http://www.spoj.com/problems/GSS6/
#include <cstdio>
#include <cassert>
#include "treap.h"
using namespace std;
#define forn(i,n) for(int i=0;i<(int)(n);i++)
struct Datos
{
int x;
int treeSize;
int bestSum, bestPrefix, bestSuffix, totalSum;
Datos(int _x = 0) {totalSum = bestSum = x = _x; bestPrefix = bestSuffix = max(0, _x); treeSize = 1;}
void lazyPropagation(Nodo<Datos> *) { }
void update(Nodo<Datos> *node)
{
// Este codigo tiene copy paste donde originalmente hacia un par de forn(i,2)
// Sepan disculpar, pero eso fue relevante para que entre en SPOJ, un server altamente estricto.
int BP[2];
int BS[2];
int TSum[2], TSize[2];
if (node->h(0))
{
BP[0] = node->h(0)->dat.bestPrefix;
BS[0] = node->h(0)->dat.bestSuffix;
TSum[0] = node->h(0)->dat.totalSum;
TSize[0] = node->h(0)->dat.treeSize;
}
else
BP[0] = BS[0] = TSum[0] = TSize[0] = 0;
if (node->h(1))
{
BP[1] = node->h(1)->dat.bestPrefix;
BS[1] = node->h(1)->dat.bestSuffix;
TSum[1] = node->h(1)->dat.totalSum;
TSize[1] = node->h(1)->dat.treeSize;
}
else
BP[1] = BS[1] = TSum[1] = TSize[1] = 0;
treeSize = 1 + TSize[0] + TSize[1];
bestSum = BS[0] + x + BP[1];
if (node->h(0)) bestSum = max(bestSum, node->h(0)->dat.bestSum);
if (node->h(1)) bestSum = max(bestSum, node->h(1)->dat.bestSum);
bestPrefix = max(BP[0], TSum[0] + x + BP[1]);
bestSuffix = max(BS[1], TSum[1] + x + BS[0]);
totalSum = TSum[0] + TSum[1] + x;
}
};
ostream & operator <<(ostream &o, const Datos &d)
{
return o << "bestSum=" << d.bestSum;
}
#define tam(p) ((p) ? (p)->dat.treeSize : 0)
Nodo<Datos> *iesimo(int i, Treap<Datos> &t)
{
Nodo<Datos> *p = t.root;
while (true)
{
assert(p);
int L = tam(p->h(0));
if (i < L)
p = p->h(0);
else if (i == L)
return p;
else
{
i -= L + 1;
p = p->h(1);
}
}
}
int main()
{
#ifdef ACMTUYO
freopen("example3.in","r",stdin);
#endif
int N; scanf("%d", &N);
const int MAXN = 100100;
static Datos v[MAXN];
forn(i,N)
{
int x;
scanf("%d", &x);
v[i] = Datos(x);
}
Treap<Datos> t(v, N+1); // Un dummy extra para evitar irnos de rango con iesimo
int Q; scanf("%d", &Q);
forn(q,Q)
{
char op[8];
scanf("%s", op);
if (op[0] == 'I')
{
int x,y;
scanf("%d%d", &x,&y);
x--;
// Esto es parecido (pero bien diferente :P) al codigo de insertarAUnladoPointer, pero empezando en p en lugar de en root
// De entrada me comi que era hacer lo mismo exacto que insertarAUnLado, y pegue WA.
// Y luego me comi otro WA por olvidarme la linea p = p->h(0); :P
// Moraleja: esto seria bastante mas error prone que el split obvio.
Nodo<Datos> *p = iesimo(x, t), *nodo = new Nodo<Datos>(y);
int lado = 0;
if (p->h(0))
{
p = p->h(0);
lado = 1;
while (p->h(1)) p = p->h(1);
}
p->hang(lado, nodo);
nodo->flotar();
t.reroot();
}
else if (op[0] == 'D')
{
int x;
scanf("%d", &x);
x--;
t.erasePointer(iesimo(x, t));
}
else if (op[0] == 'R')
{
int x,y;
scanf("%d%d", &x, &y);
x--;
Nodo<Datos> *p = iesimo(x, t);
p->dat.x = y;
p->fullUpdate();
}
else if (op[0] == 'Q')
{
int x,y;
scanf("%d%d", &x,&y);
x--;
assert(x < y);
Treap<Datos> t2,t3;
t.splitPointer(iesimo(x, t), t2);
t2.splitPointer(iesimo(y-x, t2), t3);
printf("%d\n", t2.root->dat.bestSum);
t.merge(t2);
t.merge(t3);
}
else
assert(false);
}
return 0;
}