【bzoj2002】【LCT】弹飞绵羊

本文介绍了一种利用LCT树链剖分算法解决动态路径查询问题的方法。通过构建特殊的树结构并支持动态边的修改,文章详细阐述了如何高效地查询某节点到根节点的距离,适用于路径长度动态变化的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 题意:给一段序列和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;
}
WPS Office 2019 是一款功能丰富的办公软件套装,它整合了文字、表格、演示、PDF 等组件,具备体积小巧、功能丰富、兼容性强等特点,能满足日常办公的多种需求。 功能组件丰富:包含 WPS 文字、WPS 演示、WPS 表格、WPS PDF 等组件,可用于文档编辑、表格计算、幻灯片制作、PDF 处理等,支持 DOC、DOCX、XLS、XLSX、PPT 等多种格式,能与 Microsoft Office 较好地兼容。 支持云存储与协作:用户登录 WPS 账号后,可实现多终端、跨平台的数据同步,还能与他人协同办公,文档可通过微信、QQ 等社交平台一键分享。 PDF 功能强大:提供沉浸式 PDF 阅读体验和稳定的编辑服务,支持一键编辑 PDF 文档内容。借助 OCR 技术,可精准转换文档、表格、PPT、图片等格式的文件。 界面设计优化:具有全新视觉设计,默认皮肤舒适清爽,还支持桌面背景、界面字体、皮肤、格式图标等个性化设置。同时,文档标签可拖拽成独立窗口或合并,用户可自主选择文档显示方式,还能将文件放置在不同工作区,便于分类浏览与管理。 内置实用工具:内置了简单的网页浏览器,点击文档中的链接会默认用其打开,可进行网页添加到首页、另存为 PDF 等操作。此外,“应用中心” 集成了输出转换、文档助手、安全备份等多种实用功能。 模板资源丰富:稻壳商城提供了大量模板、范文、图片等素材资源,涵盖求职简历、总结计划、合同协议等常见文档类型,方便用户快速创建专业文档。 表格功能特色突出:支持通过关键词快速切换工作表,设有阅读模式和护眼模式。还可分类合并单元格,以及拆分合并单元格并填充内容。公式编辑器中可轻松完成公式嵌套,筛选时可通过 “仅筛选此项” 一步完成特定值筛选,还能根据筛选条件生成动态分析图表。另外,“特色功能” 和 “智能工具箱” 菜单中包含 PDF
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值