问题 4283 --次大值求和(sum)

4283: 次大值求和(sum)★★★

时间限制: 1 Sec  内存限制: 128 MB
提交: 107  解决: 56
[提交][状态][命题人:]

题目描述

在绍兴市编程达人的聚会中,厌倦了求最大值的新昌小伙伴想出了一个求次大值的方案,想来考考大家。

给定一个1到n的数字各出现一次的排列a[1]、a[2]、…、a[n],定义f(l,r)表示a[l]、a[l+1]、a[l+2]、…、a[r]中的次大值,你需要求出对于所有的1<=i<j<=n,f(i,j)的和。

【数据范围约定】

对于30%的数据,n<=100;

对于70%的数据,n<=5000;

对于100%的数据,n<=100000。

#include<bits/stdc++.h> 
#define LL long long
using namespace std;
const int MAXN=100005;
struct T{ 
  int v,id; //v存放读入元素值,id存放读入顺序号
}x[MAXN];
int pre[MAXN],nxt[MAXN];
int cmp(T t1,T t2){ return t1.v<t2.v; }
void del(int p){
    int L=pre[p],r=nxt[p];
    nxt[L]=r; pre[r]=L;
}
int main(){
    int m,n,i,j,k; 
    scanf("%d",&n);
    for(i=1;i<=n;i++){    
	 scanf("%d",&x[i].v);
          x[i].id=_____①_____;
	      pre[i]=i-1; 
		  nxt[i]=i+1;
	    }
	    nxt[0]=1; 
		   pre[n+1]=n;
	    _____②____;
	    LL ans=0;
	    for(i=1;i<=n;i++){
	        LL L1,L2,r1,r2;
	        L1=pre[x[i].id];
	        if(L1) L2=pre[L1]; else L2=-1;
	        r1=nxt[x[i].id];
	        if(r1!=n+1) r2=nxt[r1]; else r2=-1;
	        if(L2!=-1) ans+=___③____*i;
	        if(r2!=-1) ans+=___④____*i;
	        del(_____⑤____);
	    }
	    printf("%lld",ans);
}  


输入

第一行一个整数n,第二行n个整数表示a[i]。

输出

一行一个整数,表示答案。

样例输入
Copy
3
2 3 1
样例输出
Copy
5

提示

样例1:区间[1,2]和[1,3]的次大值是2,区间[2,3]的次大值是1,求和后的结果为5。

样例输入2

8

8 2 7 3 4 5 6 1

样例输出2

136

来源

[提交][状态]