[线段树] BZOJ2957: 楼房重建

本文介绍了一种使用线段树来维护上升序列长度的方法,通过实现特定的数据结构和算法,能够有效地解决寻找最长上升子序列的问题。文章提供了完整的源代码,并通过具体的实现细节展示了如何更新节点值以及查询序列长度。

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

经典题,线段树维护上升序列。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define Max(p) p->_max
#define lenL(p) p->lenL
#define lenR(p) p->lenR
using namespace std;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
    char ch=gc(); int res=0;
    while(!('0'<=ch&&ch<='9')) ch=gc();
    while('0'<=ch&&ch<='9') res=(res<<3)+(res<<1)+ch-'0', ch=gc();
    return res;
}
const int maxn=400010;
struct node{
    node* ch[2];
    int L,R,lenL; double _max;
    node(int t1=0,int t2=0,double t3=0,int t4=0,node* t5=0){L=t1;R=t2;_max=t3;lenL=t4;ch[0]=ch[1]=t5;}
    int findL(double x){
        if(_max==0) return 0;
        if(L==R) return x<_max;
        if(Max(ch[0])<x) return ch[1]->findL(x);
                    else return ch[0]->findL(x)+lenL-lenL(ch[0]); 
    }
    void maintain(){
        _max=Max(ch[0])>Max(ch[1])?Max(ch[0]):Max(ch[1]);
        lenL=lenL(ch[0])+ch[1]->findL(Max(ch[0]));
    }
} *root, nil, *null=&nil;
typedef node* P_node;
P_node Build(int L,int R){
    P_node p=new node(L,R,0,0,null);
    if(L==R) return p;
    int mid=(L+R)>>1;
    p->ch[0]=Build(L,mid); p->ch[1]=Build(mid+1,R);
    return p;
}
void Updata(P_node p,int pos,double val){
    if(pos<p->L||p->R<pos) return;
    if(p->L==p->R){ p->_max=val, p->lenL=(val==0?0:1); return; }
    Updata(p->ch[0],pos,val); Updata(p->ch[1],pos,val);
    p->maintain();
}
int n,Q;
int main(){
    freopen("bzoj2957.in","r",stdin);
    freopen("bzoj2957.out","w",stdout);
    scanf("%d%d",&n,&Q);
    root=Build(1,n);
    while(Q--){
        int x=getint(),y=getint();
        Updata(root,x,(double)y/x);
        printf("%d\n",root->findL(0));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值