1. 程式人生 > >【HNOI2010】彈飛綿羊 - LCT

【HNOI2010】彈飛綿羊 - LCT

bsp swa mon span cut 直線 can 輸入格式 color

題目描述

某天,Lostmonkey發明了一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個遊戲。遊戲一開始,Lostmonkey在地上沿著一條直線擺上n個裝置,每個裝置設定初始彈力系數ki,當綿羊達到第i個裝置時,它會往後彈ki步,達到第i+ki個裝置,若不存在第i+ki個裝置,則綿羊被彈飛。綿羊想知道當它從第i個裝置起步時,被彈幾次後會被彈飛。為了使得遊戲更有趣,Lostmonkey可以修改某個彈力裝置的彈力系數,任何時候彈力系數均為正整數。

輸入輸出格式

輸入格式:

第一行包含一個整數n,表示地上有n個裝置,裝置的編號從0到n-1。

接下來一行有n個正整數,依次為那n個裝置的初始彈力系數。

第三行有一個正整數m,

接下來m行每行至少有兩個數i、j,若i=1,你要輸出從j出發被彈幾次後被彈飛,若i=2則還會再輸入一個正整數k,表示第j個彈力裝置的系數被修改成k。

輸出格式:

對於每個i=1的情況,你都要輸出一個需要的步數,占一行。

思路

LCT模板題,把這n個裝置看作n+1個節點,

n+1為虛擬節點,到達這個點即被彈飛,初

始時對每個節點進行link(i,i+k[i]),修改時先

cut(i,i+k[i]),再link(i,i+K),並讓k[i] = K

#include <bits/stdc++.h>
using namespace
std; const int maxn = 200000 + 10; struct Link_Cut_Tree { struct Splay { int ch[2],f,mark,sum,w; }t[maxn]; inline bool getfa(int x) { return t[t[x].f].ch[1] == x; } inline bool isroot(int x) { return t[t[x].f].ch[0] != x && t[t[x].f].ch[1] != x; } inline void pushup(int x) { t[x].sum = t[t[x].ch[0
]].sum+t[t[x].ch[1]].sum+t[x].w; } inline void rev(int x) { t[x].mark ^= 1; swap(t[x].ch[0],t[x].ch[1]); } inline void pushdown(int x) { if (t[x].mark) { if (t[x].ch[0]) rev(t[x].ch[0]); if (t[x].ch[1]) rev(t[x].ch[1]); t[x].mark = 0; } } inline void rotate(int x) { int f = t[x].f,g = t[f].f,c = getfa(x); if (!isroot(f)) t[g].ch[getfa(f)]=x; t[x].f = g; t[f].ch[c] = t[x].ch[c^1]; t[t[f].ch[c]].f = f; t[x].ch[c^1] = f; t[f].f = x; pushup(f); pushup(x); } inline void check(int x) { if (!isroot(x)) check(t[x].f); pushdown(x); } inline void splay(int x) { check(x); for (;!isroot(x);rotate(x)) if (!isroot(t[x].f)) rotate(getfa(t[x].f) == getfa(x) ? t[x].f : x); } inline void access(int x) { for (int y = 0;x;y = x,x = t[x].f) splay(x),t[x].ch[1] = y,pushup(x); } inline void makeroot(int x) { access(x); splay(x); rev(x); } inline int findroot(int x) { access(x); splay(x); while (t[x].ch[0]) pushdown(x),x = t[x].ch[0]; return x; } inline void link(int x,int y) { makeroot(x),t[x].f = y; } inline void cut(int x,int y) { makeroot(x); access(y); splay(y); if (t[y].ch[0] == x && t[x].ch[1] == 0) t[x].f = t[y].ch[0] = 0; } inline void split(int x,int y) { makeroot(x); access(y); splay(y); } }lct; int n,q,k[maxn]; int main() { scanf("%d",&n); for (int i = 1;i <= n+1;i++) lct.t[i].w = 1; for (int i = 1;i <= n;i++) { scanf("%d",&k[i]); lct.link(i,k[i]+i <= n ? k[i]+i : n+1); } scanf("%d",&q); while (q--) { int op,x,y; scanf("%d%d",&op,&x); x++; if (op == 1) lct.split(x,n+1),printf("%d\n",lct.t[n+1].sum-1); else { scanf("%d",&y); lct.cut(x,k[x]+x <= n ? k[x]+x: n+1); lct.link(x,y+x <= n ? y+x : n+1); k[x] = y; } } return 0; }

【HNOI2010】彈飛綿羊 - LCT