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;
    }
  • 相关阅读:
    ....
    CodeForces 375A(同余)
    POJ 2377 Bad Cowtractors (最小生成树)
    POJ 1258 AgriNet (最小生成树)
    HDU 1016 Prime Ring Problem(全排列)
    HDU 4460 Friend Chains(bfs)
    POJ 2236 Wireless Network(并查集)
    POJ 2100 Graveyard Design(尺取)
    POJ 2110 Mountain Walking(二分/bfs)
    CodeForces 1059B Forgery(模拟)
  • 原文地址:https://www.cnblogs.com/song-/p/9769716.html
Copyright © 2011-2022 走看看