題目大意:有$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個裝置,則綿羊被彈飛...