**:
給出$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,並且...