刚学平衡树的时候写了一天,莫名其妙A了,然后瞎jb改又改错了,然后并不知道到底哪里错了,于是放弃。
然后过了几个月又重新学了平衡树专题,再拿起这道神仙题,自以为思路清晰,然而又调了一天。虽然大体思路没有问题 (本来就是大力数据结构。。。),但是细小的错误很多,令人烦躁。
这道题还是反映了我代码能力的不足,在构思的时候也粗枝大叶,很难在一开始就把所有细节思考完备。还需努力。
题意
维护数列。
每个操作都不难,基本都是平衡树基本操作。 难在把那么多操作强行堆砌在同一题。
注意
1
空间有点紧,需要回收节点。
2
第2和4操作需要打标记。
需要明确一个节点有懒标记的意义:当前节点已经修改过了,但是他的儿子还没有修改。当然你的懒标记也可以表示当前节点也没有被修改过(不建议,因为到后面会比较麻烦),但是一定要在任何时候都清晰地知道那些节点需要 p u s h _ d o w n push\_down push_down。
比如下面这张图:
在
r
o
t
a
t
e
rotate
rotate之前,假如懒标记意义是自己修改过了,那么必须保证P和Q不带有标记,而A、B、C可以带标记。但假如懒标记意义是自己还没被修改,那么就需要对A、B、C、P、Q全部进行
p
u
s
h
_
d
o
w
n
push\_down
push_down然后才可以旋转。
3
不要修改0号点的权值。为了保证0号点不会“影响查找第k个点”或者“最大子段和的更新”,
0号点
s
i
z
=
0
,
m
a
x
_
s
u
m
=
−
i
n
f
siz=0,max\_sum=-inf
siz=0,max_sum=−inf
假如你像我一样在splay里面加了左右两个边界点的话,把边界的权值设为
−
i
n
f
-inf
−inf。
4
不要复制粘贴,不然有可能死得不明不白。
finally
留足耐心。。。做好调半天的准备。。。
代码
不仅长得不行,而且慢得不行。
正常版
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x = 0, fh = 0;
char c = getchar();
while (c < '0' || c > '9'){if (c == '-') fh = 1; c = getchar();}
while (c >= '0' && c <= '9') x = (x<<1)+(x<<3)+c-'0', c = getchar();
return fh ? -x : x;
}
const int inf = 1e9+7;
const int N = 5e5+10;
namespace SPLAY
{
struct TrashBin{
int bin[N], bcnt, cnt;
inline void recyc(int x){
bin[++bcnt] = x;
}
inline int new_node(){
if (bcnt) return bin[bcnt--];
return ++cnt;
}
}bin;
struct Node{
int fa, ch[2];
int siz, val, sum;
int flp, all;
int le, ri, tot;
Node(){}
Node(int _fa, int _val){
ch[0] = ch[1] = flp = all = 0; siz = 1;
fa = _fa; sum = val = _val;
tot = _val; le = ri = max(0, _val);
}
}nd[N];
int root;
#define ls nd[u].ch[0]
#define rs nd[u].ch[1]
inline void push_down(int u){
if (nd[u].all){
nd[u].all = nd[u].flp = 0;
if (ls > 2){
nd[ls].val = nd[u].val;
nd[ls].sum = nd[ls].val*nd[ls].siz;
if (nd[u].val > 0) nd[ls].le = nd[ls].ri = nd[ls].tot = nd[ls].sum;
else nd[ls].le = nd[ls].ri = 0, nd[ls].tot = nd[ls].val;
nd[ls].all = 1;
}
if (rs > 2){
nd[rs].val = nd[u].val;
nd[rs].sum = nd[rs].val*nd[rs].siz;
if (nd[u].val > 0) nd[rs].le = nd[rs].ri = nd[rs].tot = nd[rs].sum;
else nd[rs].le = nd[rs].ri = 0, nd[rs].tot = nd[rs].val;
nd[rs].all = 1;
}
}
if (nd[u].flp){
nd[u].flp = 0;
nd[ls].flp ^= 1; nd[rs].flp ^= 1;
swap(nd[ls].ch[0], nd[ls].ch[1]);
swap(nd[ls].le, nd[ls].ri);
swap(nd[rs].ch[0], nd[rs].ch[1]);
swap(nd[rs].le, nd[rs].ri);
}
}
inline void push_up(int u){
nd[u].siz = nd[ls].siz+nd[rs].siz+1;
nd[u].sum = nd[ls].sum+nd[rs].sum+nd[u].val;
nd[u].le = max(nd[ls].le, nd[ls].sum+nd[u].val+nd[rs].le);
nd[u].ri = max(nd[rs].ri, nd[rs].sum+nd[u].val+nd[ls].ri);
nd[u].tot = max(max(nd[ls].tot, nd[rs].tot), nd[u].val+nd[ls].ri+nd[rs].le);
}
void reset(int le_bd, int ri_bd){
nd[0] = Node(0, 0); nd[0].siz = 0; nd[0].tot = -inf;
nd[1] = Node(0, le_bd);
nd[2] = Node(1, ri_bd); nd[1].ch[1] = 2;
push_up(1);
root = 1; bin.cnt = 2; bin.bcnt = 0;
}
inline int son(int u){
return nd[nd[u].fa].ch[1] == u;
}
inline void rotate(int u){
int v = nd[u].fa, w = nd[v].fa;
int vs = son(u), ws = son(v);
nd[w].ch[ws] = u;
nd[v].fa = u;
nd[v].ch[vs] = nd[u].ch[vs^1];
nd[nd[u].ch[vs^1]].fa = v;
nd[u].fa = w;
nd[u].ch[vs^1] = v;
push_up(v); push_up(u);
}
inline void splay(int u, int goal){
while (nd[u].fa != goal){
if (nd[nd[u].fa].fa != goal) rotate(son(u) == son(nd[u].fa) ? nd[u].fa : u);
rotate(u);
}
if (goal == 0) root = u;
}
#undef ls
#undef rs
}
using namespace SPLAY;
int n, m, a[N];
inline void find_rnk(int root, int x)
{
int u = root;
while (u){
push_down(u);
if (nd[nd[u].ch[0]].siz >= x){u = nd[u].ch[0]; continue;}
x -= nd[nd[u].ch[0]].siz+1;
if (x == 0) break;
u = nd[u].ch[1];
}
splay(u, nd[root].fa);
}
inline void insert(int pos, int tot, int *a)
{
find_rnk(root, pos+2);
find_rnk(nd[root].ch[0], pos+1);
int u, fa = nd[root].ch[0];
for (int i = 1; i <= tot; ++ i){
u = bin.new_node();
nd[fa].ch[1] = u;
nd[u] = Node(fa, a[i]);
fa = u;
}
splay(u, 0);
}
void del_dfs(int u)
{
if (!u) return;
bin.recyc(u);
del_dfs(nd[u].ch[0]);
del_dfs(nd[u].ch[1]);
}
inline void delet(int pos, int tot)
{
find_rnk(root, pos);
find_rnk(nd[root].ch[1], tot+1);
del_dfs(nd[nd[root].ch[1]].ch[0]);
nd[nd[root].ch[1]].ch[0] = 0;
splay(nd[root].ch[1], 0);
}
inline void reverse(int pos, int tot)
{
find_rnk(root, pos);
find_rnk(nd[root].ch[1], tot+1);
int u = nd[nd[root].ch[1]].ch[0];
nd[u].flp ^= 1;
swap(nd[u].ch[0], nd[u].ch[1]);
swap(nd[u].le, nd[u].ri);
push_down(u);
splay(u, 0);
}
inline void make_same(int pos, int tot, int c)
{
find_rnk(root, pos);
find_rnk(nd[root].ch[1], tot+1);
int u = nd[nd[root].ch[1]].ch[0];
nd[u].all = 1; nd[u].val = c; nd[u].sum = c*nd[u].siz;
if (c > 0) nd[u].le = nd[u].ri = nd[u].tot = nd[u].sum;
else nd[u].le = nd[u].ri = 0, nd[u].tot = c;
push_down(u);
splay(u, 0);
}
inline int get_sum(int pos, int tot)
{
find_rnk(root, pos);
find_rnk(nd[root].ch[1], tot+1);
return nd[nd[nd[root].ch[1]].ch[0]].sum;
}
int main()
{
reset(-inf, -inf);
n = read(); m = read();
for (int i = 1; i <= n; ++ i) a[i] = read();
insert(0, n, a);
for (; m--; ){
char opt[10]; int pos, tot, x;
scanf("%s", opt);
if (opt[2] == 'X') printf("%d\n", nd[root].tot);
else {
pos = read(); tot = read();
if (opt[0] == 'G') printf("%d\n", get_sum(pos, tot));
else if (opt[0] == 'R') reverse(pos, tot);
else if (opt[2] == 'K') x = read(), make_same(pos, tot, x);
else if (opt[0] == 'D') delet(pos, tot);
else if (opt[0] == 'I'){
for (int i = 1; i <= tot; ++ i) a[i] = read();
insert(pos, tot, a);
}
}
}
return 0;
}
有调试
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x = 0, fh = 0;
char c = getchar();
while (c < '0' || c > '9'){if (c == '-') fh = 1; c = getchar();}
while (c >= '0' && c <= '9') x = (x<<1)+(x<<3)+c-'0', c = getchar();
return fh ? -x : x;
}
const int inf = 1e9+7;
const int N = 5e5+10;
namespace SPLAY
{
struct TrashBin{
int bin[N], bcnt, cnt;
inline void recyc(int x){
bin[++bcnt] = x;
}
inline int new_node(){
if (bcnt) return bin[bcnt--];
return ++cnt;
}
}bin;
struct Node{
int fa, ch[2];
int siz, val, sum;
int flp, all;
int le, ri, tot;
Node(){}
Node(int _fa, int _val){
ch[0] = ch[1] = flp = all = 0; siz = 1;
fa = _fa; sum = val = _val;
tot = _val; le = ri = max(0, _val);
}
}nd[N];
int root;
#define ls nd[u].ch[0]
#define rs nd[u].ch[1]
inline void push_down(int u){ // lazy_tag means that the current node has already been updated but sons haven't
if (nd[u].all){
nd[u].all = nd[u].flp = 0;
if (ls > 2){
nd[ls].val = nd[u].val;
nd[ls].sum = nd[ls].val*nd[ls].siz;
if (nd[u].val > 0) nd[ls].le = nd[ls].ri = nd[ls].tot = nd[ls].sum;
else nd[ls].le = nd[ls].ri = 0, nd[ls].tot = nd[ls].val;
nd[ls].all = 1;
}
if (rs > 2){
nd[rs].val = nd[u].val;
nd[rs].sum = nd[rs].val*nd[rs].siz; // !!!
if (nd[u].val > 0) nd[rs].le = nd[rs].ri = nd[rs].tot = nd[rs].sum;
else nd[rs].le = nd[rs].ri = 0, nd[rs].tot = nd[rs].val;
nd[rs].all = 1;
}
}
if (nd[u].flp){
nd[u].flp = 0;
nd[ls].flp ^= 1; nd[rs].flp ^= 1;
swap(nd[ls].ch[0], nd[ls].ch[1]);
swap(nd[ls].le, nd[ls].ri);
swap(nd[rs].ch[0], nd[rs].ch[1]);
swap(nd[rs].le, nd[rs].ri);
}
}
inline void push_up(int u){
nd[u].siz = nd[ls].siz+nd[rs].siz+1;
nd[u].sum = nd[ls].sum+nd[rs].sum+nd[u].val;
nd[u].le = max(nd[ls].le, nd[ls].sum+nd[u].val+nd[rs].le);
nd[u].ri = max(nd[rs].ri, nd[rs].sum+nd[u].val+nd[ls].ri);
nd[u].tot = max(max(nd[ls].tot, nd[rs].tot), nd[u].val+nd[ls].ri+nd[rs].le);
}
void reset(int le_bd, int ri_bd){
nd[0] = Node(0, 0); nd[0].siz = 0; nd[0].tot = -inf;
nd[1] = Node(0, le_bd);
nd[2] = Node(1, ri_bd); nd[1].ch[1] = 2;
push_up(1);
root = 1; bin.cnt = 2; bin.bcnt = 0;
}
inline int son(int u){
return nd[nd[u].fa].ch[1] == u;
}
inline void rotate(int u){
int v = nd[u].fa, w = nd[v].fa;
int vs = son(u), ws = son(v);
nd[w].ch[ws] = u;
nd[v].fa = u;
nd[v].ch[vs] = nd[u].ch[vs^1];
nd[nd[u].ch[vs^1]].fa = v;
nd[u].fa = w;
nd[u].ch[vs^1] = v;
push_up(v); push_up(u);
}
inline void splay(int u, int goal){
while (nd[u].fa != goal){
if (nd[nd[u].fa].fa != goal) rotate(son(u) == son(nd[u].fa) ? nd[u].fa : u);
rotate(u);
}
if (goal == 0) root = u;
}
#undef ls
#undef rs
}
using namespace SPLAY;
int n, m, a[N];
//void dfs(int u)
//{
// if (!u) return;
// push_down(u);
// dfs(nd[u].ch[0]);
// cout << nd[u].val << " ";
// dfs(nd[u].ch[1]);
//}
//
//void dfs1(int u)
//{
// if (!u) return;
// push_down(u);
// cout << u << " " << nd[u].ch[0] << " " << nd[u].ch[1] << " " << nd[u].val << " " << nd[u].siz << " " << nd[u].sum << " " << nd[u].tot << " " << nd[u].le << " " << nd[u].ri << endl;
// dfs1(nd[u].ch[0]);
// dfs1(nd[u].ch[1]);
//}
inline void find_rnk(int root, int x)
{
int u = root;
while (u){
push_down(u);
if (nd[nd[u].ch[0]].siz >= x){u = nd[u].ch[0]; continue;}
x -= nd[nd[u].ch[0]].siz+1;
if (x == 0) break;
u = nd[u].ch[1];
}
splay(u, nd[root].fa);
}
inline void insert(int pos, int tot, int *a)
{
find_rnk(root, pos+2);
find_rnk(nd[root].ch[0], pos+1);
int u, fa = nd[root].ch[0];
for (int i = 1; i <= tot; ++ i){
u = bin.new_node();
nd[fa].ch[1] = u;
nd[u] = Node(fa, a[i]);
fa = u;
}
splay(u, 0);
}
void del_dfs(int u)
{
if (!u) return;
bin.recyc(u);
del_dfs(nd[u].ch[0]);
del_dfs(nd[u].ch[1]);
}
inline void delet(int pos, int tot)
{
find_rnk(root, pos);
find_rnk(nd[root].ch[1], tot+1);
del_dfs(nd[nd[root].ch[1]].ch[0]);
nd[nd[root].ch[1]].ch[0] = 0;
splay(nd[root].ch[1], 0);
}
inline void reverse(int pos, int tot)
{
find_rnk(root, pos);
find_rnk(nd[root].ch[1], tot+1);
int u = nd[nd[root].ch[1]].ch[0];
nd[u].flp ^= 1;
swap(nd[u].ch[0], nd[u].ch[1]);
swap(nd[u].le, nd[u].ri);
push_down(u);
splay(u, 0);
}
inline void make_same(int pos, int tot, int c)
{
// cout << "========================================" << endl;
// dfs(root); cout << endl; dfs1(root); cout << endl;
// cout << "========================================" << endl;
find_rnk(root, pos);
find_rnk(nd[root].ch[1], tot+1);
// cout << "========================================" << endl;
// dfs(root); cout << endl;dfs1(root); cout << endl;
// cout << "========================================" << endl;
int u = nd[nd[root].ch[1]].ch[0];
nd[u].all = 1; nd[u].val = c; nd[u].sum = c*nd[u].siz;
if (c > 0) nd[u].le = nd[u].ri = nd[u].tot = nd[u].sum;
else nd[u].le = nd[u].ri = 0, nd[u].tot = c;
push_down(u);
// cout << "========================================" << endl;
// dfs(root); cout << endl;dfs1(root); cout << endl;
// cout << "========================================" << endl;
splay(u, 0);
}
inline int get_sum(int pos, int tot)
{
find_rnk(root, pos);
find_rnk(nd[root].ch[1], tot+1);
// cout << "========================================" << endl;
// dfs1(nd[nd[root].ch[1]].ch[0]); cout << endl;
// cout << "========================================" << endl;
return nd[nd[nd[root].ch[1]].ch[0]].sum;
}
int main()
{
// freopen("t.in", "r", stdin);
// freopen("t.out", "w", stdout);
reset(-inf, -inf);
n = read(); m = read();
for (int i = 1; i <= n; ++ i) a[i] = read();
insert(0, n, a);
for (; m--; ){
char opt[10]; int pos, tot, x;
scanf("%s", opt);
if (opt[2] == 'X') printf("%d\n", nd[root].tot);
else {
pos = read(); tot = read();
if (opt[0] == 'G') printf("%d\n", get_sum(pos, tot));
else if (opt[0] == 'R') reverse(pos, tot);
else if (opt[2] == 'K') x = read(), make_same(pos, tot, x);
else if (opt[0] == 'D') delet(pos, tot);
else if (opt[0] == 'I'){
for (int i = 1; i <= tot; ++ i) a[i] = read();
insert(pos, tot, a);
}
}
// cout << "---------------------------------------" << endl;
// dfs(root); cout << endl;
// dfs1(root);
}
return 0;
}