zoukankan      html  css  js  c++  java
  • luogu P2422 良好的感觉 单调栈

    题目描述

    kkk做了一个人体感觉分析器。每一天,人都有一个感受值Ai,Ai越大,表示人感觉越舒适。在一段时间[i, j]内,人的舒适程度定义为[i, j]中最不舒服的那一天的感受值 * [i, j]中每一天感受值的和。现在给出kkk在连续N天中的感受值,请问,在哪一段时间,kkk感觉最舒适?

    输入输出格式

    输入格式:

    第一行为N,代表数据记录的天数

    第二行N个整数,代表每一天的感受值

    输出格式:

    一行,表示在最舒适的一段时间中的感受值。

    题解: 

    看上去无从下手,不妨枚举那个最不舒服的感受值(即一段区间中最小值).
    令 $f_{i}$ 表示 $i$ 位置为最小值所能扩展的最大区间的感受值之和.
    用一个单调递增的队列维护最小感受值.
    考虑新加入一个元素 $a_{i}$.
    如果当前队首大于 $a_{i}$,那么 $i$ 就是队首能扩展到的最大位置了,弹出队首,把队首的 $f_{j}$ 值加上 $sum(i-1)-sum(j)$,一直反复弹栈操作.
    最后,将 $a_{i}$ 推进.
    因为栈时单调递增的,$a_{i}$ 再栈中前一个元素肯定小于等于 $a_{i}$,所以当前的贡献就是 $f_{i}=sum(i)-sum(q_{top})$.
    但是.....1. 多个元素大小相等怎么办 ? 2. 到最后都弹不掉怎么办 ?
    在最后加入一个 0,即可解决上述问题. 
    #include<bits/stdc++.h>
    #define maxn 1000000 
    #define ll long long 
    using namespace std;
    void setIO(string s)
    {
    	string in=s+".in"; 
    	freopen(in.c_str(),"r",stdin);    
    }
    int S[maxn],top,n; 
    ll f[maxn],sumv[maxn],arr[maxn];  
    int main()
    {
    	// setIO("input"); 
    	S[++top]=0;     
    	scanf("%d",&n); 
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%lld",&arr[i]); 
    		sumv[i]=sumv[i-1]+arr[i]; 
    		while(arr[S[top]] > arr[i]) 
    		{
    			f[S[top]] += sumv[i-1]-sumv[S[top]];          
    			--top; 
    		}
    		f[i]=sumv[i]-sumv[S[top]];     
    		S[++top]=i;       
    	}
    	ll ans=0; 
    	for(int i=1;i<=n;++i) ans=max(ans,f[i]*arr[i]); 
    	printf("%lld
    ",ans); 
        return 0; 
    }
    

      

  • 相关阅读:
    是男人就下100层【第二层】——帮美女更衣(1)
    是男人就下100层【第一层】——高仿微信界面(10)
    禁用JavaScript控制台调试
    是男人就下100层【第一层】——高仿微信界面(9)
    我的书单
    JSP判断移动设备
    是男人就下100层【第一层】——高仿微信界面(8)
    是男人就下100层【第一层】——高仿微信界面(7)
    是男人就下100层【第一层】——高仿微信界面(6)
    psd缩略图生成上传解决方案
  • 原文地址:https://www.cnblogs.com/guangheli/p/11047237.html
Copyright © 2011-2022 走看看