您的位置:首页 > 其它

【bzoj2002】【LCT】弹飞绵羊

2016-12-28 16:24 260 查看
题意:给一段序列和k[i]表示从i能弹到i+k[i],要求支持动态修改k值,查询由i点几次能被弹出序列长度

数据范围:对于100%的数据n<=200000,m<=100000

题解:首先对于一个点,可以从这个点向i+k[i]连一条边,i+k[i]>n时连向n这个点,显然一个点只向后连一条边,就是一棵树,求得答案就是i节点在以n+1为根的树中的深度

问题转化成了给一个树支持动态修改一条边连的点,求某一点的深度

问题又转化成了LCT裸题

修改先删除再插入

裸题一道,只可惜我太弱了,就因为cut的q p写反了调了一个晚上加一早晨。画了一张纸的树

直接放代码吧 样例过了基本就过了

#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXN 200111
using namespace std;
struct node{
int size,rev,num;
node *ch[2],*fa;
int dir(){return this==fa->ch[1];}
void cnct(node *p,int d){ch[d]=p;p->fa=this;}
void up(){size=ch[0]->size+ch[1]->size+1;}
void down();
}tnull,*null=&tnull,*tree[MAXN];
void node::down(){
if(this==null) return;
if(rev){
rev=0;
if(ch[0]!=null)ch[0]->rev^=1;
if(ch[1]!=null)ch[1]->rev^=1;
swap(ch[0],ch[1]);
}
}
node* getnode(int u){
node *p=new node();
p->size=1;p->rev=0;p->ch[0]=p->ch[1]=p->fa=null;p->num=u;
return p;
}
bool isroot(node *p){
return p==null||p->fa->ch[0]!=p&&p->fa->ch[1]!=p;
}
void rot(node *p){
if(isroot(p)) return;
int d=p->dir();node *x=p->fa;
if(x==x->fa->ch[0])
x->fa->ch[0]=p;
else if(x==x->fa->ch[1])
x->fa->ch[1]=p;
p->fa=x->fa;
x->cnct(p->ch[!d],d);
p->cnct(x,!d);
x->up();
}
void splay(node *p){
static node *sta[MAXN];int top=0;
sta[++top]=p;
for(node *k=p;!isroot(k);k=k->fa)
sta[++top]=k->fa;
while(top) sta[top--]->down();
while(!isroot(p)){
if(isroot(p->fa)) {rot(p);break;}
else
if(p->dir()==p->fa->dir()) rot(p->fa),rot(p);
else rot(p),rot(p);
}
p->up();
}
void access(node *p){
node *q=null;
while(p!=null){
splay(p);
p->cnct(q,1);
p->up();
q=p;
p=p->fa;
}
}
void mtr(node *p){
access(p);
splay(p);
p->rev=1;
}
void link(node *p,node *q){

mtr(p);
p->fa=q;
}
void cut(node *p,node *q){
mtr(p);
access(q);
splay(q);
q->ch[0]=q->ch[0]->fa=null;
q->up();
}

int query(node *p,node *q){
mtr(q);
access(p);
splay(p);
return p->size;
}
int n,m;
int f[MAXN];
int main(){
scanf("%d",&n);
for(int i=1;i<=n+1;i++)
tree[i]=getnode(i);
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);f[i]=x+i;
if(f[i]>n+1) f[i]=n+1;
link(tree[i],tree[f[i]]);
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d",&a);
if(a==1){
scanf("%d",&b);b++;
printf("%d\n",query(tree[b],tree[n+1])-1);
}
else{
scanf("%d%d",&b,&c);b++;
cut(tree[b],tree[f[b]]);
f[b]=min(b+c,n+1);
link(tree[b],tree[f[b]]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj LCT