codeforces E. Monotonic Renumeration(线段树做法)

本文探讨了使用线段树解决区间覆盖问题的方法,通过构建和更新线段树,实现对区间内元素的有效管理和查询。文章详细介绍了线段树的构建、传播、变更和查询操作,并通过一个具体的例子展示了算法的实现过程。

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

在这里插入图片描述
蛮水的一道题,就是线段覆盖。
可用线段树维护区间值,若某区间总和为0,则说明该区间任何一个点都没有被覆盖
代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;

struct qq
{
    ll w,ip;
}q[200005];
ll a[200005],d[200005],mod=998244353;
struct node
{
    ll l,r,pre,add;
}sum[800005];
bool cmp(qq a,qq b)
{
    if(a.w<b.w)
    {return 1;}
    if(a.w==b.w)
    {
        if(a.ip<b.ip)
        {return 1;}
        return 0;
    }
    return 0;
}
void build(ll l,ll r,ll os)
{
    sum[os].l=l;
    sum[os].r=r;
    if(l==r)
    {sum[os].pre=0;
    return;}
    ll mid=(l+r)/2;
    build(l,mid,os*2);
    build(mid+1,r,os*2+1);
    sum[os].pre=sum[os*2].pre+sum[os*2+1].pre;
}
void spread(ll os)
{
    if(sum[os].add)
    {
        sum[os*2].pre+=(sum[os].add*(sum[os*2].r-sum[os*2].l+1));
        sum[os*2+1].pre+=(sum[os].add*(sum[os*2+1].r-sum[os*2+1].l+1));
        sum[os*2].add+=sum[os].add;
        sum[os*2+1].add+=sum[os].add;
        sum[os].add=0;
    }
}
void change(ll x,ll y,ll os)
{
    if(x<=sum[os].l&&y>=sum[os].r)
    {
        sum[os].pre+=(sum[os].r-sum[os].l+1);
        sum[os].add+=1;
        return;
    }
    spread(os);
    ll mid=(sum[os].l+sum[os].r)/2;
    if(x<=mid)
    {change(x,y,os*2);}
    if(y>mid)
    {change(x,y,os*2+1);}
    sum[os].pre=sum[os*2].pre+sum[os*2+1].pre;
}
ll query(ll x,ll y,ll os)
{
    if(x<=sum[os].l&&y>=sum[os].r)
    {return sum[os].pre;}
    spread(os);
    ll mid=(sum[os].l+sum[os].r)/2;
    ll ans=0;
    if(x<=mid)
    {ans+=query(x,y,os*2);}
    if(y>mid)
    {ans+=query(x,y,os*2+1);}
    return ans;
}
int main()
{
    ll n,ans=1;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {scanf("%lld",&a[i]);q[i].w=a[i];q[i].ip=i;}
    sort(q+1,q+1+n,cmp);
    build(1,n,1);
    for(int i=1;i<=n;i++)
    {d[i]=q[i].w;}
    ll p1=lower_bound(d+1,d+1+n,a[1])-d;
    ll p2=upper_bound(d+1,d+1+n,a[1])-d;
    /
    ll x=q[p1].ip,y=q[p2-1].ip;
    change(x,y,1);
    for(int i=2;i<=n;i++)
    {
        p1=lower_bound(d+1,d+1+n,a[i])-d;
        p2=upper_bound(d+1,d+1+n,a[i])-d;
        x=q[p1].ip;y=q[p2-1].ip;
        if(query(x,y,1)==0)
        {change(x,y,1);
        ans=(ans*2)%mod;}
        else
        {change(x,y,1);}
    }
    printf("%lld\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值