HNOI2002 營業額統計

2021-06-28 10:24:25 字數 2944 閱讀 3193

花了一天鑽研了splay,然後發現splay沒我想象的那麼難……以前都是寫sbt來著……  但是splay的速度確實沒那麼快,但是真的挺好寫的~

我寫的版本測了這題以後又用了一下別人的splay,發現通過這題大多數splay在750ms上下,我是688ms,說明還算是不錯的啦~啦啦啦~

#include #include #include #include using namespace std;

struct node

node(int tmp, node *tmp_node):count(1), key(tmp), left_son(null), right_son(null), father(tmp_node){}

}*proot = new node;

//返回a指標的兒子數量

#define rnc(a) ((a)==null?0:a->count)

void pg(node &t)

void zag(node &x)

void splay(node &x)

if (&x == y -> left_son)

else

}else

else

} }proot = &x;

}node* search_node(int valve, node &t = *proot)//搜尋valve從t節點開始搜尋,找不到,就返回最後找到的位置

else

} return x;

}void insert_node(int valve)

node *pos(search_node(valve, *proot));

if (valve <= pos -> key)

else }

/* * 尋找從x節點為根的極大值

* 直接去search_node去找乙個極大值,一定找不到,最後找到的那個點,就是最大值

* 把最大值調整到他們通過父親節點所能追溯到的最早的節點

* ps:為何不直接調整到根?為何總是要調整? 其實都是**省事的 > 真正的效率……

*/node* exterme_max(node &x) //找從x節點為根的最大值

node* exterme_min(node &x)

/* * 從整棵樹中刪除值為valve的節點

* 找到valve,旋轉到根

* 如果只有乙個節點,那麼要特殊判斷一下

* 如果根沒有左兒子,那麼直接讓右兒子當根

* 如果有左兒子,那麼找到左兒子的最大值,旋轉到左兒子的位置上

* 此時,[根的左兒子]一定沒有[右兒子](他最大,當然沒有右兒子)

* 把[根的右兒子],並到[根的左兒子]的右兒子上

*/bool delete_node(int valve)

else

}/*找前驅

* 先找到valve,把valve旋轉到根節點

* 這個時候,根左兒子的最大值,和右兒子最小值,就是valve的前驅。 後繼同理

* ps:返回下標,有利於判斷是否不存在前驅後繼

*/node* find_node_pre(int valve)

//找後繼

node* find_node_next(int valve)

//查詢valve的排名1 ****因為本題沒有設計查排名操作,所以查排名操作沒有驗證對錯

/* * 查詢valve排名,和其他二叉樹方法一樣

*/int rank_node(int valve)

else

}ans += rnc(x -> left_son);

return ans;

}//查排名操作2

int find_rank_node(int valve)

int n, tmp, ans;

int main()

cout << ans << endl;

return 0;

}

花了時間研究zkw splay tree,也就是自頂向下維護的神奇splay,各種快!而且程式更短功能更好用!!!決定用這個程式當模板了!

強烈推薦,速度快了6倍!

#include #include #include using namespace std;

const int maxint = 0x7fffffff;

struct node

node (int key_, node *c0, node *c1):

key(key_)

node* rz()

} tnull, *null = &tnull;

struct splay

void zig(bool d)

void zigzig(bool d)

void finish(bool d)

root -> c[!d] = p;

} void select(int k)

if (dd) k -= t + 1;

d != dd ? zig(d), zig(dd) : zigzig(d);

} finish(0), finish(1);

root -> rz();

} void search(int x)

d != dd ? zig(d), zig(dd) : zigzig(d);

} finish(0); finish(1);

root -> rz();

if (x > root -> key) select(root -> c[0] -> size + 1);

} void ins(int x)

void del(int x)

int sel(int k)

int ran(int x)

}sp;

int n, tmp, ans;

int main()

t2 = b = sp.sel(rank + 1);

// cout<

HNOI 2002 營業額統計

最近開始重新學習splay樹寫的第一題,基本就是照著別人部落格改的一道題,關於splay樹的模板,感覺大牛已經把 改得很短!這道題沒什麼難度,乙個插入操作,乙個找前驅,乙個找後驅的操作。話說這題有個資料有個bug的地方,可以看連線的discuss 因為沒有push down,push up的操作,感...

HNOI2002 營業額統計

傳送門 題目大意 求一段序列,小於當前元素的最大值和大於當前元素的最小值。從該元素前面的元素找。題解 建立線段樹維護或者使用雙向鍊錶.或stl水過 線段樹每次插入乙個新值,查詢大於它的最小值和小於它的最大值 雙向鍊錶有點神.我們知道排序後乙個數的前驅就是小於它的最大值 後繼就是大於它的最小值,我們將...

HNOI2002 營業額統計

其實這個題不用平衡樹也可以過的?資料太水了啊 但是我還是本著聯絡平衡樹的想法打了一遍平衡樹。既然是最小的波動,那麼直接找前驅後繼就可以了呀qwq 如下 include include include include define maxn 100010 using namespace std int...