• 南昌网络赛 I. Max answer (单调栈 + 线段树)


    https://nanti.jisuanke.com/t/38228

    题意
    给你一个序列,对于每个连续子区间,有一个价值,等与这个区间和×区间最小值,
    求所有子区间的最大价值是多少。

    分析:我们先用单调栈预处理 区间 [L[i] , R[i] ] 最小值为a[i] , 的L[i] , R[i] ;

    首先我们明白 , 如果a[i] >0 那 [L[i] , R[i] ] , 里面的数都是正数 , 所以应该全选 ;

    a[i] < 0 , 那我们 应该在[L[i]-1 , i-1] 这里面找到前缀和最大 , 在[i,R[i]] 这里找到前缀和最小

    这样的区间和才是最大

    我。。。比赛的时候被自己秀死 , 判断a[i] >0 竟然也用了线段树的做法 , 导致边界没有控制好

    #include <iostream>
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    #include <math.h>
    #include <queue>
    #define MAXN 500001
    #define inf 0x3f3f3f3f
    
    using namespace std;
    const int N=500001;
    typedef long long ll;
    
    int a[N],L[N],R[N],s[N],top;
    ll sum[N],ans=-0x7f7f7f7f,n,h[N];
    ll l=1,r=1;
    struct node{
        int l,r;//区间[l,r]
    
    
        ll mx; //区间最大值
        ll mn; //区间最小值
    }tree[MAXN<<2];//一定要开到4倍多的空间
    
    void pushup(int index){
    
        tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);
        tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);
    }
    
    int cnt;
    void build(int l,int r,int index){
        tree[index].l = l;
        tree[index].r = r;
    
        if(l == r){
           // scanf("%d",&tree[index].sum);
            tree[index].mn = tree[index].mx =sum[++cnt];
            return ;
        }
        int mid = (l+r)>>1;
        build(l,mid,index<<1);
        build(mid+1,r,index<<1|1);
        pushup(index);
    }
    
    ll queryMIN(int l,int r,int index){
        if(l <= tree[index].l && r >= tree[index].r){
            //return tree[index].sum;
    
        return tree[index].mn;
        }
    
        int mid = (tree[index].l+tree[index].r)>>1;
    
    
        ll Min =0x7f7f7f7f;
        if(l <= mid){
    
           // Max = max(query(l,r,index<<1),Max);
            Min = min(queryMIN(l,r,index<<1),Min);
        }
        if(r > mid){
    
          //  Max = max(query(l,r,index<<1|1),Max);
            Min = min(queryMIN(l,r,index<<1|1),Min);
        }
        //return ans;
    
        return Min;
        //return Min;
    }
    ll queryMAX(int l,int r,int index){
        if(l <= tree[index].l && r >= tree[index].r){
            //return tree[index].sum;
            return tree[index].mx;
            //return tree[index].mn;
        }
    
        int mid = (tree[index].l+tree[index].r)>>1;
    
        ll Max = -0x7f7f7f7f;
    
        if(l <= mid){
    
            Max = max(queryMAX(l,r,index<<1),Max);
           // Min = min(query(l,r,index<<1),Min);
        }
        if(r > mid){
    
            Max = max(queryMAX(l,r,index<<1|1),Max);
            //Min = min(query(l,r,index<<1|1),Min);
        }
        //return ans;
    
        return Max;
        //return Min;
    }
    int main()
    {
    
    
        ios::sync_with_stdio(false);
        cin>>n;
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            sum[i]=sum[i-1]+a[i];
    
        }
        build(1,n+1,1);
    
    
    
        top=0;
        for(int i=1;i<=n;i++)
        {
            while(top&&a[s[top]]>=a[i])
                --top;
            L[i]=(top==0?1:s[top]+1);
            s[++top]=i;
        }
        top=0;
        for(int i=n;i>=1;i--)
        {
            while(top&&a[s[top]]>=a[i])
                --top;
            R[i]=(top==0?n:s[top]-1);
            s[++top]=i;
        }
       // cout<<queryMIN(2,2,1)<<endl;
        for(int i=1;i<=n;i++)
        {
            ll temp;
            if(a[i]>0)
            {
    
           temp =(sum[R[i]] - sum[L[i]-1])*a[i];
    //       cout<<L[i]<<" "<<R[i]<<endl;
    //       cout<<queryMAX(i,R[i],1)<<" "<<queryMIN(L[i]-1,i-1,1)<<endl;
            }
            else if(a[i]<0)
            {
    
                    if(L[i]==1 && queryMAX(max(1,L[i]-1),max(1,i-1),1)<0)
                        temp=(queryMIN(i,R[i],1))*a[i];
                    else
                    temp =(queryMIN(i,R[i],1)-queryMAX(max(1,L[i]-1),max(1,i-1),1))*a[i];
    
    //       cout<<queryMAX(L[i]-1,i-1,1)<<" "<<queryMIN(i,R[i],1)<<endl;
    
            }
            else if(a[i]==0)
                temp=0;
    //        else if(a[i]<0)
    //        {
    //            temp=(queryMIN(R[i],i,1) - queryMAX(L[i],i,1))*a[i];
    //        }
            if(temp>ans) {ans=temp;}
        }
    
        cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    Jquery(智能感知AJAX,从后台调数据)
    jQuery插件(输入关键字出现提示,并可查询)
    设置缓存失效的三种方法
    关于fluorinefx基础和服务器搭建的文章地址
    关于过河问题的感悟
    .net 大文件上传
    iis7中运行cmd
    学习总结
    C#开源资源项目(转载)
    HTML数据提取
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10745122.html
Copyright © 2020-2023  润新知