NOI 2005 BZOJ 1500 維護數列

2021-07-09 07:22:44 字數 2627 閱讀 8991

這道算是一道合格的splay基礎題。距離上一次那道簡單的splay時間比較長,因為經歷了元旦晚會和之後的乙個小假期沒寫題。

這道題涵蓋的splay的操作還是比較多的,適合練手。寫的時候思路一定要清晰,否則不好調。

推薦自頂向下寫。我就是先寫的最大的框架,判斷輸入,呼叫哪個函式。寫出大框架之後就輪到挨個寫函式了,這些函式也是有上下關係的,最靠上的當然就是最直接的對應每個操作的函式。我使用**和合併操作來完成它們。這樣很簡單地寫完了這些函式。之後就該寫其下一層的**和合併,其中涉及到splay,pushdown和maintain,思路清晰,很快寫好。之後寫下一層的splay,這個函式寫得很簡短,就用到了rotate。再最後,就應該寫最底層的pushdown,maintain,rotate和find。一氣呵成,寫完**大概用了1個小時多一點。

然而,除錯的過程有一點坎坷(被cogs坑了一下,本地怎麼跑都沒事,cogs上就是全t,完全沒有輸出,加了記憶體池優化空間後在bzoj上是過了)。細節較多的是mx的維護,在maintain中需要注意一下。還有就是maintain的呼叫的時間,以及呼叫時要保證合法性(比如偷懶的我在maintain裡沒有判斷lc和rc是否為0就直接拿它們更新rt,那麼就要保證lc或rc是0的時候的su,ml,mr,mx不會影響到rt)。

#include 

#include

#include

#include

using namespace std;

void get (int &x)

while (c <= '9' && c >= '0') x = x

*10+c-48, c = getchar();

if (neg) x = -x;

}void get (char *s)

void put (int

x) char s[15]; int num = 0;

while (x) s[++num] = (x

%10)+48, x /= 10;

while (num) putchar(s[num--]);

putchar ('\n');

}int max (int a, int b, int c, int d, int e)

queue mem;

struct node

};struct splaytree

if (p[rt].re)

}//int va, lc, rc, fa, sz, ch, re, su, ml, mr, mx;

void maintain (int rt)

int makenewtree (int tot)

int find (int rt, int k)

void reuse (int rt)

void rotate (int rt)

else

if(p[gfa].lc == fa) p[gfa].lc=rt; else p[gfa].rc=rt;

p[rt].fa = gfa;

maintain(fa); maintain(rt);

}void splay (int rt)

}int

split (int rt, int op) // 1 left 0 right

void merge (int l, int r)

if (!r)

root = l;

splay (find(root,p[root].sz));

pushdown(root);

p[root].rc = r, p[r].fa = root;

maintain(root);

}void insert (int

pos, int tot)

}void erase (int

pos, int tot)

else

}void update (int

pos, int tot)

void rever (int

pos, int tot)

void getsum (int

pos, int tot)

int op = split (find(root,pos),1);

int op2= split (find(root,tot),0);

put (p[root].su);

merge (root,op2);

merge (op, root);

}void maxsum (int

pos, int tot)

}solve;

int n, m;

int getcommand()

int main()

if (cmd == 1) solve.insert(pos, tot);

if (cmd == 2) solve.erase (pos, tot);

if (cmd == 3) solve.update(pos, tot);

if (cmd == 4) solve.rever (pos, tot);

if (cmd == 5) solve.getsum(pos, tot);

if (cmd == 0) solve.maxsum(pos, tot);

}return

0;}

BZOJ1500 NOI2005 維修數列

description input 輸入檔案的第1行包含兩個數n和m,n表示初始時數列中數的個數,m表示要進行的運算元目。第2行包含n個數字,描述初始時的數列。以下m行,每行一條命令,格式參見問題描述中的 output 對於輸入資料中的get sum和max sum操作,向輸出檔案依次列印結果,每個...

bzoj1500 NOI2005 維修數列

splay鼻祖級的題目?霧。insert 把第pos個數 有哨兵節點 轉到root,把第pos 1個數轉到root的右兒子,然後對c建樹然後把這棵樹插到root右兒子的左兒子處 delete 把第pos個數轉到root,把第pos tot 1個數轉到root右兒子,刪掉root右兒子的左兒子 變成0...

BZOJ 1500 NOI2005 維修數列

輸入的第1 行包含兩個數n 和m m 20 000 n 表示初始時數列中數的個數,m表示要進行的運算元目。第2行包含n個數字,描述初始時的數列。以下m行,每行一條命令,格式參見問題描述中的 任何時刻數列中最多含有500 000個數,數列中任何乙個數字均在 1 000,1 000 內。插入的數字總數不...