poj3667 线段树区间更新

本文讨论了在处理大型数据集时,通过优化数据结构和代码逻辑,提高算法效率的经验。具体包括了如何识别并删除冗余部分,简化更新操作,并提供了简洁的AC代码实现。重点在于记录左连续、右连续和全局连续的数据状态,以解决实际问题。

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

一开始想复杂了,记录了6个值,代码量相当的大而且update比较麻烦,后来query的时候发现其中有两个值没用,有一个值可以减掉,果断删了重写,虽然wrong了1次,不过还算顺利,A了后看大神的代码,果然够简洁,小改了一下。总体来说,记录左连续,右连续,全局连续就ok了。


ACcode:

#include<stdio.h>
#include<iostream>
using namespace std;

const int size=55555;

struct Node
{
    int lc,rc,mc;
    int lazy,sum;
} tre[size<<2];

int Max(int a1,int a2)
{
    return a1>a2?a1:a2;
}

int Min(int a1,int a2)
{
    return a1<a2?a1:a2;
}

void pushup(int rt)
{
     int r1=rt<<1,r2=r1|1;
     if (tre[r1].lc==tre[r1].sum) tre[rt].lc=tre[r1].lc+tre[r2].lc;
     else tre[rt].lc=tre[r1].lc;
     if (tre[r2].rc==tre[r2].sum) tre[rt].rc=tre[r1].rc+tre[r2].rc;
     else tre[rt].rc=tre[r2].rc;
     tre[rt].mc=Max(tre[r1].rc+tre[r2].lc,Max(tre[r1].mc,tre[r2].mc));
}

void build(int rt,int l,int r)
{
    tre[rt].lazy=-1;
    tre[rt].sum=r-l+1;
    if (l==r)
    {
        tre[rt].lc=tre[rt].rc=tre[rt].mc=1;
        return ;
    }
    int m=(l+r)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
    pushup(rt);
}

void pushdown(int rt,int l,int r)
{
    if (tre[rt].lazy>=0)
    {
        int m=(l+r)>>1;
        int r1=rt<<1,r2=r1|1,v=tre[rt].lazy;
        tre[r1].mc=tre[r1].lc=tre[r1].rc=(m-l+1)*v;
        tre[r2].mc=tre[r2].lc=tre[r2].rc=(r-m)*v;
        tre[r1].lazy=tre[r2].lazy=tre[rt].lazy;
        tre[rt].lazy=-1;
    }
}

void update(int rt,int l,int r,int L,int R,int v)
{
    if (L<=l&&r<=R)
    {
        tre[rt].mc=tre[rt].lc=tre[rt].rc=(r-l+1)*v;
        tre[rt].lazy=v;
        return ;
    }
    if (l==r) return ;
    pushdown(rt,l,r);
    int m=(l+r)>>1;
    if (L<=m) update(rt<<1,l,m,L,R,v);
    if (R>m) update(rt<<1|1,m+1,r,L,R,v);
    pushup(rt);
}

int query(int rt,int l,int r,int num)
{
    if (l==r) return r;
    pushdown(rt,l,r);
    int m=(l+r)>>1,pos;
    int r1=rt<<1,r2=r1|1;
    if (tre[r1].mc>=num) pos=query(r1,l,m,num);
    else if ((tre[r1].rc+tre[r2].lc)>=num)
         pos=m-tre[r1].rc+1;
    else pos=query(r2,m+1,r,num);
    return pos;
}

int main()
{
    int n,q,op,d,x;
    while (~scanf("%d %d",&n,&q))
    {
        build(1,1,n);
        while (q--)
        {
            scanf("%d",&op);
            if (op==1)
            {
                scanf("%d",&x);
                if (tre[1].mc<x) d=0;
                else
                {
                   d=query(1,1,n,x);
                   update(1,1,n,d,x+d-1,0);
                }
                printf("%d\n",d);
            }
            else
            {
                scanf("%d %d",&x,&d);
                update(1,1,n,x,x+d-1,1);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值