[HNOI2010]彈飛綿羊——[LCT]
阿新 • • 發佈:2018-12-10
【題目描述】 某天,發明了一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個遊戲。遊戲一開始,在地上沿著一條直線擺上個裝置,每個裝置設定初始彈力系數,當綿羊達到第個裝置時,它會往後彈步,達到第個裝置,若不存在第個裝置,則綿羊被彈飛。綿羊想知道當它從第個裝置起步時,被彈幾次後會被彈飛。為了使得遊戲更有趣,可以修改某個彈力裝置的彈力系數,任何時候彈力系數均為正整數。
【輸入格式】 第一行包含一個整數,表示地上有個裝置,裝置的編號從到。 接下來一行有個正整數,依次為那個裝置的初始彈力系數。
第三行有一個正整數,
接下來行每行至少有兩個數、,若,你要輸出從出發被彈幾次後被彈飛,若則還會再輸入一個正整數,表示第個彈力裝置的係數被修改成k。
【輸出格式】 對於每個的情況,你都要輸出一個需要的步數,佔一行。
4 1 2 1 1 3 1 1 2 1 1 1 1
2 3
【題意分析】
一個坑點:編號從0到n-1
題目保證每隻綿羊只會往後彈,彈到後面沒有了就直接彈飛。那麼對於被彈飛,可以理解成彈到了第個點。(虛構的一個節點)
輸入的時候,設第個點設定成往後彈,那麼如果就,否則(被彈飛)
操作的時候,如果是修改,先判斷要修改的點連的是還是,先,然後跟輸入時差不多,判斷之後再。別忘了修改勁度係數!!(此處WA*1) 如果是詢問,那就,,然後輸出。
Code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#define MAXN 500000
using namespace std;
int son[MAXN][2],father[MAXN],size[MAXN],lazy[MAXN];
int a[MAXN],stack[MAXN],n,q;
namespace LCT{
inline bool isroot (int x){
return !(son[father[x]][0] == x || son[father[x]][1] == x);
}//是否為根
inline void pushup (int x){
size[x] = 1;
if (son[x][0])size[x] += size[son[x][0]];
if (son[x][1])size[x] += size[son[x][1]];
}//更新size
inline void pushdown (int x){
if (lazy[x]){
swap (son[x][0],son[x][1]);
if (son[x][0])lazy[son[x][0]] ^= 1;
if (son[x][1])lazy[son[x][1]] ^= 1;
lazy[x] = 0;
}
}
inline void rotate (int x){
int y = father[x],z = father[y];
int k = son[y][1] == x,kk = son[z][1] == y;
if (!isroot (y))son[z][kk] = x;
father[x] = z;
son[y][k] = son[x][k^1];
father[son[x][k^1]] = y;
son[x][k^1] = y;
father[y] = x;
pushup (y); pushup (x);
}
inline void splay (int x){
int top = 0;
stack[++top] = x;
for (register int i = x;!isroot (i);i = father[i])
stack[++top] = father[i];
for (register int i = top;i;i--)
pushdown (stack[i]);
while (!isroot (x)){
int y = father[x],z = father[y];
if (!isroot (y))
(son[y][1] == x) ^ (son[z][1] == y)
? rotate (x) : rotate (y);
rotate (x);
}
pushup (x);
}
inline void access (int x){
for (register int y = 0;x;y = x,x = father[x]){
splay (x);
son[x][1] = y;
pushup (x);
}
}
inline int findroot (int x){
access (x);
splay (x);
while (son[x][0]){
pushdown (son[x][0]);
x = son[x][0];
}
return x;
}
inline void makeroot (int x){
access (x);
splay (x);
lazy[x] ^= 1;
}
inline void link (int x,int y){
makeroot (x);
father[x] = y;
}
inline void cut (int x,int y){
makeroot (x);
access (y);
splay (y);
son[y][0] = father[x] = 0;
pushup (y);
}
inline int query (int x,int y){
makeroot (x);
access (y);
splay (y);
return size[y] - 1;
}
}using namespace LCT;
int main (){
scanf ("%d",&n);
for (register int i = 1;i <= n+1;i++)
size[i] = 1;
for (register int i = 1;i <= n;i++){
int x;
scanf ("%d",&x);
(i+x <= n)
? link (i,i+x) : link (i,n+1);
a[i] = x;
}
scanf ("%d",&q);
while (q--){
int type;
scanf ("%d",&type);
if (type == 1){
int x;
scanf ("%d",&x); x++;
printf ("%d\n",query (x,n+1));
}
if (type == 2){
int x,y;
scanf ("%d%d",&x,&y); x++;
(x+a[x] <= n)
? cut (x,x+a[x]) : cut (x,n+1);
(x+y <= n)
? link (x,x+y) : link (x,n+1);
a[x] = y;
}
}
return 0;
}