洛谷P3203 HNOI2010 彈飛綿羊

2022-05-24 01:30:06 字數 1367 閱讀 1423

題目大意:有$n$個節點,第$i$個節點有乙個彈力係數$k_i$,當到達第$i$個點時,會彈到第$i+k_i$個節點,若沒有這個節點($i+k_i>n$)就會被彈飛。有兩個操作:

$x:$詢問從第$x$個節點開始要多少次會被彈飛

$x,y:$把第$x$個點的彈力係數修改為$y$。

題解:建乙個節點標號$n+1$,所有大於$n$的位置都連向這,表示會被彈飛。其他每個節點向會被彈到的節點連邊($i->k_i+i$),發現這樣會構成一棵樹。

詢問就是問該點的深度(到$n+1$的距離)。修改就是把原來的邊切斷,再連上一條新邊。可以想到$lct$,只需要維護每個點到鏈頂的距離即可。

卡點:1.$get$函式寫錯

2.在$link$和$cut$操作中換了根,但是在詢問中是按照根為$n+1$來做的

c++ code:

#include #define maxn 200010

#define lc(rt) son[rt][0]

#define rc(rt) son[rt][1]

using namespace std;

int sz[maxn], son[maxn][2], fa[maxn], tg[maxn];

inline int min(int a, int b)

inline void swap(int &a, int &b)

inline int get(int rt, int flag = 1)

inline bool is_root(int rt)

inline void update(int rt)

inline void pushdown(int rt)

inline void rotate(int x)

int stack[maxn], top;

inline void splay(int x)

inline void access(int rt)

inline void make_root(int rt)

inline void link(int x, int y)

inline void split(int x, int y)

inline void cut(int x, int y)

int n, m;

inline int ask(int rt)

int s[maxn];

int main()

scanf("%d", &m);

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

}return 0;

}

洛谷 P3203 HNOI2010 彈飛綿羊

有n個點,第i個點有乙個ki,表示到達i這個點後可以到i ki這個點 支援修改ki和詢問一點走幾次能走出所有點兩個操作 分塊,對於每個點,維護它走到下一塊所經過的點數,它走到下一塊到的店的編號 每次修改只會對這塊左端點到這個點產生影響 include include using namespace ...

P3203 HNOI2010 彈飛綿羊

題目大意 有n個裝置,每個裝置設定初始彈力係數ki,當達到第i個裝置時,會往後彈ki步,達到第i ki個裝置,若不存在第i ki個裝置,則被彈飛。求從第i個裝置起步時,被彈幾次後會被彈飛。帶修改操作,下標0開始 分析 開始打算倒著跑一遍記錄每個位置彈飛要多少次,但是發現這樣做修改操作複雜度 為了減少...

P3203 HNOI2010 彈飛綿羊

某天,lostmonkey發明了一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個遊戲。遊戲一開始,lostmonkey在地上沿著一條直線擺上n個裝置,每個裝置設定初始彈力係數ki,當綿羊達到第i個裝置時,它會往後彈ki步,達到第i ki個裝置,若不存在第i ki個裝置,則綿羊被彈飛...