P3203 [HNOI2010]弹飞绵羊(LCT)
思路
首先在每个弹力装置和它能到达的弹力装置处连边
会发现长的像一颗树一样
然后涉及到了修改,就是动态的连边和删除边,可以想到用LCT维护
然后对于修改,cut掉原来的边,再link新的节点即可
查询把(j,x+10)split出来,然后x+10节点中存放的就是需要的信息,去掉本身的sz就是1之后就是答案
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct SPT{
int son[2],sz,tag;
}SPT[200100];
int fa[200100],n,a[200100],m;
void pushup(int o){
SPT[o].sz=SPT[SPT[o].son[0]].sz+SPT[SPT[o].son[1]].sz+1;
}
void pushdown(int o){
if(o&&SPT[o].tag){
SPT[SPT[o].son[0]].tag^=1;
SPT[SPT[o].son[1]].tag^=1;
swap(SPT[o].son[0],SPT[o].son[1]);
SPT[o].tag=0;
}
}
bool isrl(int o){
return o==SPT[fa[o]].son[1];
}
bool isroot(int o){
return (SPT[fa[o]].son[0]!=o)&&(SPT[fa[o]].son[1]!=o);
}
void rorate(int o){
if(isroot(o))
return;
int f=fa[o];
int g=fa[f];
int which=isrl(o);
pushdown(f);
pushdown(o);
//o--g
fa[o]=g;
if(!isroot(f))
SPT[g].son[SPT[g].son[1]==f]=o;
//
fa[SPT[o].son[which^1]]=f;
SPT[f].son[which]=SPT[o].son[which^1];
SPT[o].son[which^1]=f;
fa[f]=o;
pushup(f);
pushup(o);
}
void push(int o){
if(!isroot(o))
push(fa[o]);
pushdown(o);
}
void splay(int o){
push(o);
for(int f;!isroot(o);rorate(o)){
if(!isroot(f=fa[o]))
rorate((isrl(f)==isrl(o))?f:o);
}
}
void access(int o){
for(int y=0;o;o=fa[y=o])
splay(o),SPT[o].son[1]=y,pushup(o);
}
void makeroot(int o){
access(o);
splay(o);
SPT[o].tag^=1;
pushdown(o);
}
int findroot(int o){
access(o);
splay(o);
pushdown(o);
while(SPT[o].son[0])
pushdown(o=SPT[o].son[0]);
return o;
}
void split(int x,int y){
makeroot(x);
access(y);
splay(y);
}
void link(int x,int y){
makeroot(x);
if(findroot(y)!=x)
fa[x]=y;
}
void cut(int x,int y){
makeroot(x);
if(findroot(y)==x&&fa[x]==y&&SPT[y].son[0]==x&&SPT[x].son[1]==0)
fa[x]=0,SPT[y].son[0]=0,pushup(y);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
SPT[i].sz=1;
}
SPT[n+10].sz=1;
for(int i=1;i<=n;i++)
link(i,(i+a[i]>n)?n+10:i+a[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++){
int opt,j,k;
scanf("%d %d",&opt,&j);
j++;
if(opt==1){
split(j,n+10);
printf("%d\n",SPT[n+10].sz-1);
}
else{
scanf("%d",&k);
cut(j,(j+a[j]>n)?n+10:j+a[j]);
a[j]=k;
link(j,(j+a[j]>n)?n+10:j+a[j]);
}
}
}