P2801 教主的魔法

  这题真的挺简单的……模拟的时候我十五分钟就切掉了……

  维护区间最值,查询的时候 w > 最大返回0,w <= 最小返回区间长度,否则找两个子区间。

  我把模拟代码交到洛谷上50分……发现自己在找子区间的时候忘了pushdown……(模拟数据真的好水啊……听说直接暴力改都满分……)

  但是常数可能有点大,这个要看题是否故意卡掉线段树了。个人认为,这道题想卡什么都很容易……

  whisper:数据下次不要这么水可以嘛…

  代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
#define maxn 4000005
#define ls now<<1
#define rs now<<1|1
int lazy[maxn],M[maxn],S[maxn],l[maxn],r[maxn];
int n,m;
void up(int now)
{
    M[now]=max(M[ls],M[rs]);
    S[now]=min(S[ls],S[rs]);
}
void build(int now,int L,int R)
{
    l[now]=L;
    r[now]=R;
    if(L==R)
    {
        scanf("%d",&M[now]);
        S[now]=M[now];
        return ;
    }
    int mid=(L+R)>>1;
    build(ls,L,mid);
    build(rs,mid+1,R);
    up(now);
}
void pushdown(int now)
{
    if(!lazy[now]) return ;
    lazy[ls]+=lazy[now];
    lazy[rs]+=lazy[now];
    M[ls]+=lazy[now];
    S[ls]+=lazy[now];
    M[rs]+=lazy[now];
    S[rs]+=lazy[now];
    lazy[now]=0;
}
void update(int now,int L,int R,int w)
{
    if(l[now]==L&&r[now]==R)
    {
        M[now]+=w;
        S[now]+=w;
        lazy[now]+=w;
        return ;
    }
    pushdown(now);
    int mid=(l[now]+r[now])>>1;
    if(R<=mid) update(ls,L,R,w);
    else if(L>mid) update(rs,L,R,w);
    else 
    {
        update(ls,L,mid,w);
        update(rs,mid+1,R,w);
    }
    up(now);
}
int query(int now,int L,int R,int w)
{
    if(l[now]==L&&r[now]==R)
    {
        if(l[now]!=r[now]) pushdown(now); 
        if(M[now]<w) return 0;
        else if(S[now]>=w) return r[now]-l[now]+1;
        else return query(ls,l[ls],r[ls],w)+query(rs,l[rs],r[rs],w);
    }
    pushdown(now);
    int mid=(l[now]+r[now])>>1;
    if(R<=mid) return query(ls,L,R,w);
    else if(L>mid) return query(rs,L,R,w);
    else return query(ls,L,mid,w)+query(rs,mid+1,R,w);
}
int main()
{
    //freopen("magic.in","r",stdin);
    //freopen("magic.out","w",stdout);
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        char s;
        int L,R,w;
        cin>>s;
        scanf("%d%d%d",&L,&R,&w);
        if(s=='M')
            update(1,L,R,w);
        else printf("%d\n",query(1,L,R,w));
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/popo-black-cat/p/10989167.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值