【csp模拟赛6】计数--单调栈
对于60%的数据:暴力枚举对于100%的数据:因为排列是随机的,所以从每个点向后可能的差值最多2logn个,所以答案最多只可能有nlogn种,用单调队列找出来统计即可
维护对于每个位置,向右能影响到的点的下一个点,统计答案时一直跳即可
代码:
#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 */