洛谷P2596 書架 splay

2022-05-02 20:09:10 字數 3125 閱讀 1074

**:

給出$n$本書和$m$個操作,按照操作維護序列並輸出對應結果。

建立書本編號對樹上節點的對映,對於$top$和$bottom$操作,先把其前驅旋到根,後繼旋到根的右兒子,目標節點就是根的右兒子的左兒子。記錄其節點編號,然後斷開,把節點加到樹的最前或者最後。對於$insert$操作,如果是$0$直接忽略,否則與前驅和後繼交換編號值和對應對映。對於$ask$和$query$操作,就是平衡樹值求權值和權值求值的基本操作。

ac**:

#include using namespace std;

const int maxn = 6e5 + 5;

int hs[maxn], a[maxn];

struct splay

void pushup(int x) }

int getson(int x)

void con(int x, int y, int z)

void rotate(int x)

void splay(int x, int end)

if (!end)

rt = x;

} int newnode(int x,int f)

int build(int f, int l, int r)

int pre_nxt(int m)

int minmax(int m)

//work

void top_bot(int id, int m) }

void insert(int id, int m) }

int querynum(int x,int rnk)

if (son[now][0])

rnk -= size[son[now][0]];

if (rnk == 1)

rnk -= 1;

now = son[now][1];

} }int queryrnk(int id)

void print(int x) };

splay sp;

int main()

else if (str[0] == 't')

sp.top_bot(x, 0);

else if (str[0] == 'b')

sp.top_bot(x, 1);

else if (str[0] == 'a')

printf("%d\n", sp.queryrnk(x) - 1);

else if (str[0] == 'q')

printf("%d\n", sp.val[sp.querynum(sp.rt, x)]);

//printf("\n");

}return 0;

}

使用結構體儲存書本的資訊,包括書本的編號和權值。開始時按照$1~n$記錄書本的權值,並且設$l$和$r$分別為$1$和$n$,對於$top$操作和$bottom$操作,先找到書本對應的結點編號,然後$--l$或者$++r$賦給目標節點的權值,然後把原結點刪除再插入新結點,$insert$就是先找到兩個結點然後交換權值資訊再重新刪除和插入。$ask$和$query$是基本操作。

ac**:

#include using namespace std;

const int maxn = 1.5e5 + 5;

int id[maxn];

struct splay

; node(){}

}; node val[maxn];

int fa[maxn], son[maxn][2], size[maxn];

int num[maxn];

int sz, rt;

bool cmp(node& a, node& b)

void swp(node& a, node& b)

void pushup(int x) }

void con(int x, int y, int z)

int getson(int x)

void rotate(int x)

void splay(int x, int end)

if (!end)

rt = x;

} void clear(int x)

int newnode(node x, int f)

void insert(node x)

int now = rt, f = 0;

while (1)

f = now, now = son[now][cmp(x, val[now])];

if(!now)

}} void del(int x)

else if (!son[rt][0] || !son[rt][1])

else

}int pre()

int nxt()

node querynum(int rnk)

if (son[now][0])

rnk -= size[son[now][0]];

if (rnk <= num[now])

rnk -= num[now];

now = son[now][1];

} }int queryrnk(int x)

splay(now, rt);

return size[son[rt][0]];

} // work

void top_bottom(int x, int y)//x為舊id,y為新id

void ins(int x, int mod)//x為id }

void init() };

splay sp;

typedef splay::node nd;

int main()

char str[10];

for (int i = 1; i <= m; ++i)

else if (str[0] == 't')

else if (str[0] == 'b')

else if (str[0] == 'a')

printf("%d\n", sp.queryrnk(id[a]) - 1);

else if (str[0] == 'q')

printf("%d\n", sp.querynum(a + 1).v);

} return 0;

}

P2596 ZJOI2006 書架 題解

最近學習了splay和非旋式treap,於是找到了這道題。維護乙個序列,支援移動元素,查詢元素在序列中的位置,查詢序列中某乙個位置的元素。無旋式treap可以維護一棵樹的中序遍歷結果,但是不支援通過編號來找節點。於是在無旋式treap的基礎上,維護每個節點的父親,這樣就可以求出元素在序列中的位置。對...

洛谷P2676 超級書架

farmer john最近為奶牛們的圖書館添置了乙個巨大的書架,儘管它是如此的大,但它還是幾乎瞬間就被各種各樣的書塞滿了。現在,只有書架的頂上還留有一點空間。所有n 1 n 20,000 頭奶牛都有乙個確定的身高h i 1 h i 10,000 設所有奶牛身高的和為s。書架的高度為b,並且保證 1 ...

洛谷P2676 超級書架

題目描述 farmer john最近為奶牛們的圖書館添置了乙個巨大的書架,儘管它是如此的大,但它還是幾乎瞬間就被各種各樣的書塞滿了。現在,只有書架的頂上還留有一點空間。所有n 1 n 20,000 頭奶牛都有乙個確定的身高h i 1 h i 10,000 設所有奶牛身高的和為s。書架的高度為b,並且...