HDU5751Eades

来源:互联网 发布:老站优化关键词 编辑:程序博客网 时间:2024/05/16 00:57

先处理连续一段中最大值出现位置然后用FFT计算出各个最大值出现次数时的线段树 累加答案

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<complex>#include<algorithm>#include<iostream>#include<queue>#include<vector>using namespace std;#define ll long longchar c;inline void read(int&a){a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}int n,m;int Rev[600000];inline void Bg(int n){    int L=0;    while((1<<L)^n)L++;    for(int i=0;i<n;i++)Rev[i]=(Rev[i>>1]>>1)|((i&1)<<(L-1));}#define com complex<double>const       double pi=acos(-1);com A[600000],B[600000];int S[600000];com C[600000];inline void Rader(com* a,int n){    for(int i=0;i<n;i++)if(Rev[i]>i)swap(a[Rev[i]],a[i]);}/*inline void FFT(com *a,int n,int f){    Rader(a,n);    for(int i=1;i<n;i<<=1)        {            com w0(cos(pi/i),f*sin(pi/i));            for(int j=0;j<n;j+=i<<1)                {                    com w(1,0);                    for(int k=0;k<i;k++)                    {                        com L=a[j+k],R=w*a[j+k+i];                        a[j+k]=L+R;                        a[j+k+i]=L-R;                        w=w*w0;                    }                   }        }    if(f==-1)        for(int i=0;i<n;i++)            a[i]/=n;}*/void FFT(com* a,int len,int flag){    Rader(a,len);    for(int i=1;i<len;i<<=1)    {        com W(cos(pi/i),flag*sin(pi/i));        for(int j=0;j<len;j+=i<<1)        {            com W0(1,0);            for(int k=0;k<i;k++)            {                com x=a[j+k],y=W0*a[j+k+i];                a[j+k]=x+y;                a[j+k+i]=x-y;                W0*=W;            }        }    }    if(flag==-1)    for(int i=0;i<len;i++)a[i]/=len;}int Val[60001];int     L[60001],R[60001];vector<int> Q[60001];inline bool cmp(int a,int b){return abs(a)<abs(b);}int main(){    int T;    read(T);    while(T--)    {        int n;        read(n);        for(int i=1;i<=n;i++)            Q[i].clear();        for(int i=1;i<=n;i++)        read(Val[i]),Q[Val[i]].push_back(i);        for(int i=1;i<=n;i++)        {            L[i]=i;            while(L[i]>1&&Val[i]>=Val[L[i]-1])L[i]=L[L[i]-1];            Q[Val[i]].push_back(-L[i]+1);        }        for(int i=n;i;i--)        {            R[i]=i;            while(R[i]<n&&Val[i]>=Val[R[i]+1])R[i]=R[R[i]+1];            Q[Val[i]].push_back(-R[i]-1);        }        for(int i=1;i<=n;i++)sort(Q[i].begin(),Q[i].end(),cmp);        for(int i=1;i<=n;i++)        if(!Q[i].empty())        {            int l=0,r=l+1;            while(l<Q[i].size())                {                    while(l+1<Q[i].size()&&Q[i][l+1]<=0)                    l++;                    if(l+1==Q[i].size())break;                    r=l+1;                              while(Q[i][r]>0)                        r++;                    int tl=r-l,len=1;                    while(tl>len)len*=2;                    len*=2;                    //if(len<=4)len*=2;                    //len*=2;                    for(int j=0;j<len;j++)C[j]=A[j]=0;                    Bg(len);                    A[0]=Q[i][l+1]-abs(Q[i][l]-1)+1;                    for(int j=1;j<tl-1;j++)                    A[j]=Q[i][l+j+1]-Q[i][l+j];                     A[tl-1]=abs(Q[i][r]+1)-Q[i][r-1]+1;                                     for(int j=0;j<tl-1;j++)C[j]=A[tl-1-j-1];                    FFT(A,len,1);                    FFT(C,len,1);                    for(int j=0;j<len;j++)B[j]=A[j]*C[j];                    FFT(B,len,-1);                    for(int j=0;j<tl-1;j++)                    {                        int T=int(B[j+tl-1].real()+0.5);                        S[j+1]+=T;                    }                    l=r+1;                }        }        ll Ans=0;        for(int i=1;i<=n;i++)            Ans+=i^S[i],S[i]=0;        cout<<Ans<<endl;    }    return 0;}
0 0
原创粉丝点击