Fork me on GitHub

【csp模拟赛6】计数--单调栈

60%100%2lognnlogn

维护对于每个位置,向右能影响到的点的下一个点,统计答案时一直跳即可

代码:

#include<iostream>
#include<cstdio>
using namespace std;
int T,n,top;
const int N=100010;
int a[N],mx[N],mi[N],sta[N];
long long ans;
int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*f;
}
void slove()
{
	int maxx,minn;
	for(int i=1;i<=n;++i)mx[i]=mi[i]=n+1;
	top=0;
	for(int i=1;i<=n;++i)
	{
		while(top&&a[i]>a[sta[top]])
		{
			mx[sta[top--]]=i;
		}
		sta[++top]=i;
	}
	top=0;
	for(int i=1;i<=n;++i)
	{
		while(top&&a[i]<a[sta[top]])
		{
			mi[sta[top--]]=i;
		}
		sta[++top]=i;
	}
	for(int i=1;i<=n;++i)
	{
		maxx=minn=i;
		while(maxx<=n&&minn<=n)
		{
			if(mx[maxx]<=mi[minn])
			{
				ans+=(long long)(mx[maxx]-max(maxx,minn))*(a[maxx]-a[minn]);
				maxx=mx[maxx];
			}
			else
			{
				ans+=(long long)(mi[minn]-max(maxx,minn))*(a[maxx]-a[minn]);
				minn=mi[minn];
			} 
		}
	}
}
int main()
{
	#ifdef yilnr
	#else
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
	#endif
	cin>>T;
	while(T--)
	{
		ans=0;
		n=read();
		for(int i=1;i<=n;++i)a[i]=read();
		slove();
		printf("%lld\n",ans);
	}
	fclose(stdin);fclose(stdout);
	return 0;
}
/*
3
4
3 2 4 1
4
3 2 4 1
4
3 2 4 1
*/

 

posted @ 2019-09-23 21:31  yelir  阅读(194)  评论(0编辑  收藏  举报