[Tyvj P4875]排列

来源:互联网 发布:依伊芭莎淘宝 编辑:程序博客网 时间:2024/06/05 16:56

原题链接

一开始想的是n2做法
预处理+n2枚举
然后看了题解

利用单调栈
固定左端点
右端点跳到最大最小值发生改变的地方
时间复杂度nlogn

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<queue>#include<vector>#include<climits>#include<string>#include<cstdlib>#include<ctime>#define MOD 1000000007#define LL long longusing namespace std;LL t,n,a[100005],rmax[100005],rmin[100005],top,q[100005],maxn,minn,j,j1,j2,d,ans[100005];void pre(){    LL i;    q[0]=n+1;    top=0;    for(i=n;i>=1;i--)    {        while(top&&a[q[top]]<=a[i]) top--;        rmax[i]=q[top];        top++;        q[top]=i;       }    q[0]=n+1;       top=0;    for(i=n;i>=1;i--)    {        while(top&&a[q[top]]>=a[i]) top--;        rmin[i]=q[top];        top++;        q[top]=i;       }}int main(){    LL i;    scanf("%lld",&t);    while(t--)    {        memset(ans,0,sizeof(ans));        scanf("%lld",&n);        for(i=1;i<=n;i++)            scanf("%lld",&a[i]);        pre();        for(i=1;i<=n;i++)        {            j=i;            j1=i;            j2=i;            while(j<=n)            {                if(rmax[j1]<rmin[j2])                {                    d=rmax[j1]-j;                    ans[a[j1]-a[j2]]+=d;                    j=rmax[j1];                    j1=rmax[j1];                }                           else                {                    d=rmin[j2]-j;                    ans[a[j1]-a[j2]]+=d;                    j=rmin[j2];                    j2=rmin[j2];                            }                           }        }        for(i=1;i<n;i++) ans[i]+=ans[i-1];        for(i=0;i<n;i++) printf("%lld\n",ans[i]);    }    return 0;}
原创粉丝点击