zoukankan      html  css  js  c++  java
  • 洛谷——P2801 教主的魔法(线段树or分块)

    P2801 教主的魔法

    (1) 若第一个字母为“M”,则紧接着有三个数字L、R、W。表示对闭区间 [L, R] 内所有英雄的身高加上W。

    (2) 若第一个字母为“A”,则紧接着有三个数字L、R、C。询问闭区间 [L, R] 内有多少英雄的身高大于等于C。

    线段树大法好

    维护区间$max$和区间$min$

    修改,正常修改即可,push_up操作修改的也只是区间最大值和最小值

    关键在于查找,若当前区间的最大值$<=$所要查询的值,返回0

    若当前区间的最小值$>=$所要查询的值,返回$r-l+1$

    想不到啊,维护区间最大值和最小值还能进行这样的骚操作啊,还是太蒟了。。。qwq

    这题分块可做,可蒟蒻(博主)不会啊。。。

    #include<bits/stdc++.h>
    
    #define N 10000000
    using namespace std;
    
    struct Segment{
        int l,r,mw,mi,f;
    }tr[N];
    
    void push_up(int k){
        tr[k].mi=min(tr[k<<1].mi,tr[k<<1|1].mi);
        tr[k].mw=max(tr[k<<1].mw,tr[k<<1|1].mw);
    }
    
    void build(int k,int l,int r){
        tr[k].l=l,tr[k].r=r;
        if(l==r) {scanf("%d",&tr[k].mi),tr[k].mw=tr[k].mi;return;}
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        push_up(k);
    }
    
    void push_down(int k){
        if(tr[k].f){
            int f=tr[k].f;
            tr[k<<1].mi+=f,tr[k<<1].mw+=f;
            tr[k<<1].f+=f,
            tr[k<<1|1].mi+=f,tr[k<<1|1].mw+=f;
            tr[k<<1|1].f+=f,
            tr[k].f=0;
        }
    }
    
    void update(int k,int ql,int qr,int f){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=ql&&r<=qr) {tr[k].mi+=f,tr[k].mw+=f;tr[k].f+=f;return;}
        push_down(k);
        if(ql<=mid) update(k<<1,ql,qr,f);
        if(qr>mid) update(k<<1|1,ql,qr,f);
        push_up(k);
    }
    
    int query(int k,int ql,int qr,int val){
        int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
        if(l>=ql&&r<=qr&&tr[k].mi>=val) return r-l+1;
        if(l>=ql&&r<=qr&&tr[k].mw<val) return 0;
        push_down(k);
        int ans=0;
        if(ql<=mid) ans+=query(k<<1,ql,qr,val);
        if(qr>mid) ans+=query(k<<1|1,ql,qr,val);
        push_up(k);
        return ans;
    }
    
    int n,q;
    
    int main()
    {
        scanf("%d%d",&n,&q);
        build(1,1,n);
        for(int l,r,x,i=1;i<=q;i++){
            char p;
            cin>>p;
            scanf("%d%d%d",&l,&r,&x);
            if(p=='M') update(1,l,r,x);
            else{
                printf("%d
    ",query(1,l,r,x));
            }
        }
        
        return 0;
    }
  • 相关阅读:
    1360 奇怪的电梯(lift)
    1249 Lake Counting
    1330 【例8.3】最少步数
    1329 【例8.2】细胞
    1215 迷宫
    垃圾树
    vector
    1970:【15NOIP普及组】扫雷游戏
    1251:仙岛求药
    Python3+PCAN-USB基于PCAN-Basic二次开发实现上位机功能
  • 原文地址:https://www.cnblogs.com/song-/p/9769716.html
Copyright © 2011-2022 走看看