zoukankan      html  css  js  c++  java
  • Feel Good(POJ 2796)树状数组+单调栈

    题意:

    一排数,找到一个区间,使得该区间内 所有数之和乘以该区间内的最小数 最大,输出该最大值和区间左右端点。

    Sample Input

    6
    3 1 6 4 5 2
    

    Sample Output

    60
    3 5

    冉了我好久的一道单调栈的题,毕竟我也是刚入门。

    注意的一点:ans初值要赋为-1,如果默认赋为0,当我们的数据最大值为0时就无法操作

     

    代码如下:

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    const int MX=1e5+100;
    int n;
    long long a[MX],bit[MX],L[MX],R[MX],stk[MX],top;
    
    int lowbit(int x){
        return x&-x;
    }
    
    void update(int x,int add)
    {
        for(;x<=n;x+=lowbit(x))
            bit[x]+=add;
    }
    
    long long sum(int x)
    {
        long long tot=0;
        for(;x;x-=lowbit(x))
            tot+=bit[x];
        return tot;    
    }
    
    void sol()
    {
        while(top>0) top--;
        for(int i=1;i<=n;++i)
        {
            while(top>0 && a[i]<=a[stk[top]]) top--;
            if(top==0)  L[i]=0;
            else        L[i]=stk[top];
            stk[++top]=i;                 
        }
        
        while(top>0) top--;
        for(int i=n;i>=1;--i)
        {
            while(top>0 && a[i]<=a[stk[top]]) top--; 
            if(top==0)  R[i]=n+1;
            else        R[i]=stk[top];
            stk[++top]=i;
        }
    }
    
    long long bin(int l,int r)
    {
        return sum(r)-sum(l-1);
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            memset(bit,0,sizeof(bit));
            for(int i=1;i<=n;++i)
            {
                scanf("%d",&a[i]);
                update(i,a[i]);
            }
        
            sol();
            long long ans=-1;
            int l,r;
            for(int i=1;i<=n;++i)
            {
                long long t=bin(L[i]+1,R[i]-1)*a[i];
                if(t>ans)
                {
                    ans=t;
                    l=L[i]+1;
                    r=R[i]-1;
                }
            }
            printf("%lld
    %d %d
    ",ans,l,r);
        }
        return 0;
    }
    /*
    6
    3 1 6 4 5 2
    */
    从0到1很难,但从1到100很容易
  • 相关阅读:
    eureka注册中心搭建
    MySQL基本查询语句
    通过IP地址和子网掩码与运算计算相关地址
    Linux bash 快捷键列表【转】
    Linux 系统简介【转】
    Linux Vim -d 比较两个文件
    无连接和面向连接协议的区别【转】
    ARP报文详解
    Linux 指定网卡 ping
    Linux Windows Java 快速生成指定大小的空文件
  • 原文地址:https://www.cnblogs.com/qseer/p/9398108.html
Copyright © 2011-2022 走看看