• XTU 1205 Range


    还是五月湘潭赛的题目,当时就是因为我坑。。。连个银牌都没拿到,擦。

    这个题目枚举区间是不可能的,明显是要考虑每个数对全局的影响,即找到每个数最左和最右能满足是最大的位置 以及 最小的时候,相乘即为该数字影响的区间总数。当时想到的是用线段树,建树的时候求出最大和最小值,然后在每个数往里面搜索,比赛的时候敲挫了,那个时候真的线段树写的很挫,而且没考虑过一个问题,就是相同的时候怎么办,按刚刚的算法,会算重复的,所以一个好的方法是如果有相同的,往左搜的时候搜到等于该数值的时候停止,往右搜的时候搜到大于该数值的时候停止(求最大的时候),求最小的时候也是一样的处理

    然后搜左边的时候优先走右子树,右子树没有 再找左子树。。同理右边先搜左孩子,没有再搜右孩子,注意些细节以及可以剪剪枝。

    线段树写这个题目其实很费力,有种更好的方法用桟来做,栈在求最大最小的时候往往很给力,像这个题目,我比如在求左边最大的时候,我当前数,如果碰到栈顶数比它大于等于的,就直接停止了,入桟,否则就一直pop下去,直到遇到比它大于等于的或者桟空,这个时候得到了左边区间最大,并且把当前值放进去,因为我只保留左边区间离下个数最近的最大的数即可,如果连这个数都不能阻挡下一个数,那之前被pop掉的肯定也阻挡不了,所以扫一遍即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define lson rt<<1,l,mid
    #define rson rt<<1|1,mid+1,r
    #define LL __int64
    using namespace std;
    const int N = 100010;
    int dmin[N<<2],dmax[N<<2];
    int A[N];
    int n;
    void build(int rt,int l,int r)
    {
        if (l>=r){
            dmin[rt]=A[l];
            dmax[rt]=A[l];
            return;
        }
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
        dmax[rt]=max(dmax[rt<<1],dmax[rt<<1|1]);
        dmin[rt]=min(dmin[rt<<1],dmin[rt<<1|1]);
    }
    int query1(int L,int R,int val,int rt,int l,int r)
    {
        if (L>R) return R;
        if (l>=r){
            if(l>=L &&l<=R && A[l]>=val){
                return l;
            }
            else return 0;
        }
        int mid=(l+r)>>1;
        if (R<=mid){
            if (dmax[rt<<1]>=val)
            return query1(L,R,val,lson);
            else return 0;
        }
        int ret=0;
        if (dmax[rt<<1|1]>=val){
            ret=query1(L,R,val,rson);
        }
        if (ret>0) return ret;
        if (dmax[rt<<1]>=val)
        return query1(L,R,val,lson);
        else return 0;
    }
    int query2(int L,int R,int val,int rt,int l,int r)
    {
        if (L>R) return L;
        if (l>=r){
            if (l>=L && l<=R && A[l]>=val){
                return l;
            }
            else return n+1;
        }
        int mid=(l+r)>>1;
        if (L>mid){
            if (dmax[rt<<1|1]>=val)
            return query2(L,R,val,rson);
            else return n+1;
        }
        int ret=n+1;
        if (dmax[rt<<1]>=val){
            ret=query2(L,R,val,lson);
        }
        if (ret<n+1) return ret;
        if (dmax[rt<<1|1]>=val)
        return query2(L,R,val,rson);
        else return n+1;
    }
    int query3(int L,int R,int val,int rt,int l,int r)
    {
        if (L>R) return R;
        if (l>=r){
            if (L<=l && l<=R && A[l]<=val){
                return l;
            }
            else return 0;
        }
        int mid=(l+r)>>1;
    
        if (R<=mid){
            if (dmin[rt<<1]<=val){
                return query3(L,R,val,lson);
            }
            else return 0;
        }
        int ret=0;
        if (dmin[rt<<1|1]<=val) ret=query3(L,R,val,rson);
        if (ret>0) return ret;
        if (dmin[rt<<1]<=val)
        return query3(L,R,val,lson);
        else return 0;
    }
    int query4(int L,int R,int val,int rt,int l,int r)
    {
        if (L>R) return L;
        if (l>=r){
            if (L<=l && r<=R && A[l]<=val){
                return l;
            }
            else return n+1;
        }
        int mid=(l+r)>>1;
        if (L>mid){
            if (dmin[rt<<1|1]<=val){
                return query4(L,R,val,rson);
            }
            else return n+1;
        }
        int ret=n+1;
        if (dmin[rt<<1]<=val){
            ret=query4(L,R,val,lson);
        }
        if (ret<n+1) return ret;
        else
        if (dmin[rt<<1|1]<=val) return query4(L,R,val,rson);
        return n+1;
    }
    int main()
    {
        int t;
        int kase=0;
        scanf("%d",&t);
        while (t--)
        {
            scanf("%d",&n);
            for (int i=1;i<=n;i++) scanf("%d",&A[i]);
            build(1,1,n);
            LL sum=0;
            for (int i=1;i<=n;i++){
                int l1=query1(1,i-1,A[i],1,1,n);
                int l2=query2(i+1,n,A[i]+1,1,1,n);
                int l3=query3(1,i-1,A[i],1,1,n);
                int l4=query4(i+1,n,A[i]-1,1,1,n);
                //cout<<"Test "<<i<<endl;
               // cout<<l1<<" "<<l2<<" "<<l3<<" "<<l4<<endl;
                sum+=(LL)(i-l1)*(LL)(l2-i)*(LL)A[i];
                sum-=(LL)(i-l3)*(LL)(l4-i)*(LL)A[i];
            }
            sum+=(LL)n*(n+1)/2;
            printf("Case %d: %I64d
    ",++kase,sum);
        }
        return 0;
    }
  • 相关阅读:
    Nmon 性能:分析 AIX 和 Linux 性能的免费工具
    libvirt(virsh命令总结)
    Linux之shell编程基础
    Shell之sed命令
    linux shell基础
    ubuntu apt-get 遇到的问题
    JavaScript之面向对象学九(原型式继承和寄生式继承)
    JavaScript之apply()和call()的区别
    JavaScript之面向对象学习八(继承)
    JavaScript之面向对象学习七(动态原型模式、寄生构造函数模式、稳妥构造函数模式创建自定义类型)
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3947234.html
Copyright © 2020-2023  润新知