zoukankan      html  css  js  c++  java
  • 线段树(区间最大值和最大值的个数)

    传送门:

    链接:https://ac.nowcoder.com/acm/contest/9667/B
    来源:牛客网

    牛牛有n个宝石,第i个宝石的价值是w[i].
    有m个操作,操作分为两种类型
    − Change   x  y   把第x个宝石的价值改成 y 
    − Ask          l   r   询问区间[l,r]内宝石的最大价值,和最大价值的宝石有多少个。
     
     
    线段树中查询区间最大值的时候都是上传标记的
    先查询左右节点在上传标记
    例:求和中的下传标记:
    要先下传标记在,查询左右子节点
    void push(int p){
    	t[2*p].lazy+=t[p].lazy;//下传标记 
    	t[2*p].s+=1ll*(t[2*p].r-t[2*p].l+1)*t[p].lazy;
    	
    	t[2*p+1].lazy+=t[p].lazy;
    	t[2*p+1].s+=1ll*(t[2*p+1].r-t[2*p+1].l+1)*t[p].lazy;
    	
    	t[p].lazy=0;//还原标记 
    }
    

     

    更新时:

    push(p);
    if(l<=t[2*p].r){ update(2*p,l,r,k); } if(r>=t[2*p+1].l){   update(2*p+1,l,r,k); }

    这里的上传标记(回溯的时候上传)

    上传标记的时候是根据2*p和2*p+1更新p

    void push_up(int p){
    	t[p].ma=max(t[2*p].ma,t[2*p+1].ma);
    	if(t[2*p].ma==t[2*p+1].ma){
    		t[p].cnt=t[2*p].cnt+t[2*p+1].cnt;
    	} 
    	else if(t[2*p].ma>t[2*p+1].ma){
    		t[p].cnt=t[2*p].cnt;
    	}
    	else{
    		t[p].cnt=t[2*p+1].cnt;
    	}
    }
    

    更新时:

    int mid=(t[p].l+t[p].r)/2;
        if(x<=mid){
            update(2*p,x,k);
        } 
        else{
            update(2*p+1,x,k);
        }
        push_up(p);

    就是在区间求和中建树中也上传标记了

    t[p].s=t[2*p].s+t[2*p+1].s;

    这个题就是:

    维护一个区间最值,和一个区间最值的个数,在查询的时候先找出区间最值,在找出最值出现的次数

    上传标记时:

    void push_up(int p){
        t[p].ma=max(t[2*p].ma,t[2*p+1].ma);
        if(t[2*p].ma==t[2*p+1].ma){
            t[p].cnt=t[2*p].cnt+t[2*p+1].cnt;
        } 
        else if(t[2*p].ma>t[2*p+1].ma){
            t[p].cnt=t[2*p].cnt;
        }
        else{
            t[p].cnt=t[2*p+1].cnt;
        }
    }

    AC代码:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=4e6+100; 
    int a[maxn]; 
    struct node{
        int l,r;
        int ma,cnt;
    }t[maxn];
    int ans1,n,m,x,y;
    void push_up(int p){
        t[p].ma=max(t[2*p].ma,t[2*p+1].ma);
        if(t[2*p].ma==t[2*p+1].ma){
            t[p].cnt=t[2*p].cnt+t[2*p+1].cnt;
        } 
        else if(t[2*p].ma>t[2*p+1].ma){
            t[p].cnt=t[2*p].cnt;
        }
        else{
            t[p].cnt=t[2*p+1].cnt;
        }
    }
    void build(int p,int l,int r){
        t[p].l=l;
        t[p].r=r;
        t[p].cnt=0;
        if(l==r){
            t[p].ma=a[l];
            t[p].cnt=1;
            return ;
        }
        int mid=(l+r)/2;
        build(2*p,l,mid);
        build(2*p+1,mid+1,r);
        push_up(p);
    }
    void update(int p,int x,int k){
        if(t[p].l==t[p].r){
            t[p].ma=k;
            t[p].cnt=1;
            return ;
        } 
        int mid=(t[p].l+t[p].r)/2;
        if(x<=mid){
            update(2*p,x,k);
        } 
        else{
            update(2*p+1,x,k);
        }
        push_up(p);
    } 
    void query(int p,int l,int r){
        int L=t[p].l,R=t[p].r;
        if(L>=l&&R<=r){
            ans1=max(ans1,t[p].ma);
            return ;
        }
        int mid=(L+R)/2;
        if(l<=mid){
            query(2*p,l,r); 
        }
        if(r>mid){
            query(2*p+1,l,r);
        }
        push_up(p);
    }
    int getcnt(int p,int l,int r){
        int L=t[p].l,R=t[p].r;
        if(L>=l&&R<=r&&t[p].cnt){
            if(ans1==t[p].ma){
                return t[p].cnt;
            }
            else return 0;
        }
        int z=0;
        int mid=(L+R)/2; 
        if(l<=mid){
            z+=getcnt(2*p,l,r);
        }
        if(r>mid){
            z+=getcnt(2*p+1,l,r);
        } 
        push_up(p);
        return z;
    } 
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        build(1,1,n);
        char str[maxn];
        for(int i=1;i<=m;i++){
            cin>>str>>x>>y;
            if(str[0]=='A'){
                ans1=0;
                query(1,x,y);
                printf("%d %d
    ",ans1,getcnt(1,x,y));
            }
            else{
                update(1,x,y);
            }
        }
    }
  • 相关阅读:
    括号匹配
    超级阶梯问题
    进制问题
    rwkj 1423
    next_permutation
    rwkj 1420
    uva-10392-因数分解
    uva-10305-水题-拓扑排序
    uva-10194-排序
    uva-10152-乌龟排序
  • 原文地址:https://www.cnblogs.com/lipu123/p/14095101.html
Copyright © 2011-2022 走看看