• CF817D Solution


    题目链接

    题解

    ⭐:单调栈可以维护\([1,i]\)中大于或小于\(a_i\)的元素。

    由于数据范围枚举左右端点并不现实,因此想到求出每个元素对于答案的贡献。设\([1,i)\)中最后一个\(>a_i\)的数为\(l\)\((i,n]\)中第一个\(>a_i\)的数为\(r\)\((r,l)\)即为\(a_i\)作为最大值的最大区间,其中\(l,r\)可用单调栈求出。利用乘法原理可知\(a_i\)作为最大值的区间数\(=(i-l)(r-i)\),而对答案的贡献为区间数\(\times a_i\)。 最小值同理,最终答案即为最大值贡献和\(-\)最小值贡献和。

    AC代码

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1e6+10;
    int a[N],st[N],lg[N],rg[N],ll[N],rl[N],top;
    //ll/lr[i]:a[i]作为最大值的最大区间左/右端点,lg/rg[i]:a[i]作为最小值的最大区间左/右端点
    signed main()
    {
    	int n,sum1=0,sum2=0;//sum1:最大值贡献和,sum2:最小值贡献和
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	for(int i=1;i<=n;i++) 
    	{
    		while(top && a[st[top]]>=a[i]) top--;
    		lg[i]=i-st[top]; st[++top]=i;
    	}
    	top=0,st[0]=n+1;
    	for(int i=n;i>=1;i--) 
    	{
    		while(top && a[st[top]]>a[i]) top--;
    		rg[i]=st[top]-i; st[++top]=i;
    	}
    	top=0,st[0]=0;
    	for(int i=1;i<=n;i++) 
    	{
    		while(top && a[st[top]]<=a[i]) top--;
    		ll[i]=i-st[top]; st[++top]=i;
    	}
    	top=0,st[0]=n+1;
    	for(int i=n;i>=1;i--) 
    	{
    		while(top && a[st[top]]<a[i]) top--;
    		rl[i]=st[top]-i; st[++top]=i;
    	}
    	for(int i=1;i<=n;i++) {sum1+=ll[i]*rl[i]*a[i]; sum2+=lg[i]*rg[i]*a[i];}
    	printf("%lld",sum1-sum2);
    	return 0;
    }
    
  • 相关阅读:
    PHP生成二维码并上传到七牛云
    算法入门---选择排序
    算法入门
    react入门-refs
    react入门-props.children
    react入门-组件方法、数据和生命周期
    react入门-jsx
    递归
    node的path.join 和 path.resolve的区别
    vuex的使用
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14530009.html
Copyright © 2020-2023  润新知