bzoj1145

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1145

神题。。。。。。
定义f(abcd)为高度排名为abcd的个数,例如闪电的个数为f(1324)。
我们化简一下:
 f(1324)-f(1243)-f(1432)
=f(1x2x)-f(1423)-f(12xx)+f(1234)-f(14xx)+f(1423)
=f(1x2x)+f(1234)-f(12xx)-f(14xx)
=f(1x2x)+f(1234)-[f(1xxx)-f(13xx)]
=f(1x2x)+f(13xx)+f(1234)-f(1xxx)
实验变成求f(1x2x),f(13xx),f(1234)和f(1xxx)。
其中f(1234)和f(1xxx)都比较好求,我们来重点讨论f(1x2x)和f(13xx)。
首先预处理出两个比较重要的数组l[i]和r[i]。l[i]表示1到i-1小于a[i]的个数;r[i]表示i+1到N中小于a[i]的个数。
--------------------------------------------------------------------------------------------------------------------------------------------
f(1x2x):
我们在2的位置进行统计,不妨记2的位置为i。为方便识别,我们在位置i那里涂成红色,即f(1x 2x)。
容易发现,如果我们知道了f(13 2),那么f(1x 2x)=f(13 2)*(N-i-r[i])。
于是变成了求f(13 2)。
13 2
=(13 2+31 2+12 3+21 3)-(31 2+12 3+21 3)
观察第1个括号:13 31 12 21 3
我们发现他们左边两个黑色的数中,其中一个小于红色的数,另一个可以大于或小于红色的数。
所以第1个括号为:l[i]*(l[i]-1)/2+l[i]*(i-1-l[i])
观察第2个括号:31 12 21 3
我们发现他们第2个黑色的数小于红色的数,第1个黑色的数没有限制。
所以第2个括号为:∑(j-1)(j<i且a[j]<a[i])
这个可以用树状数组实现。
--------------------------------------------------------------------------------------------------------------------------------------------
f(13xx):
我们在3的位置进行统计,记3的位置为i,把位置i那里涂成红色,即f(1 3xx)。
同样容易发现,如果我们知道了f(1 32),那么f(1 3xx)=f(1 32)*(N-i-r[i])。
注意这里的f(1 32)和上面的f(13 2)的不同之处在于统计的位置(红色)。
于是变成求f(1 32)。
1 32
=(1 32+ 312+ 321)-( 312+ 321)
观察第1个括号:1 3312  321
我们发现3的右边一定有一个2,然后1的位置随便放。
所以第1个括号为:∑(a[j]-1)(i<j且a[i]>a[j])
观察第2个括号: 312  321
其实就是  3xx
所以第2个括号为:r[i]*(r[i]-1)/2
#include<cstdio>

#include<cstdlib>

#include<iostream>

#include<fstream>

#include<algorithm>

#include<cstring>

#include<string>

#include<cmath>

#include<queue>

#include<stack>

#include<map>

#include<utility>

#include<set>

#include<bitset>

#include<vector>

#include<functional>

#include<deque>

#include<cctype>

#include<climits>

#include<complex>

//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj

 

using namespace std;



typedef long long LL;

typedef double DB;

typedef pair<int,int> PII;

typedef complex<DB> CP;



#define mmst(a,v) memset(a,v,sizeof(a))

#define mmcy(a,b) memcpy(a,b,sizeof(a))

#define re(i,a,b)  for(i=a;i<=b;i++)

#define red(i,a,b) for(i=a;i>=b;i--)

#define fi first

#define se second

#define m_p(a,b) make_pair(a,b)

#define SF scanf

#define PF printf

#define two(k) (1<<(k))



template<class T>inline T sqr(T x){return x*x;}

template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}

template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}



const DB EPS=1e-9;

inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}

const DB Pi=acos(-1.0);



inline int gint()

  {

        int res=0;bool neg=0;char z;

        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());

        if(z==EOF)return 0;

        if(z=='-'){neg=1;z=getchar();}

        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());

        return (neg)?-res:res; 

    }

inline LL gll()

  {

      LL res=0;bool neg=0;char z;

        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());

        if(z==EOF)return 0;

        if(z=='-'){neg=1;z=getchar();}

        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());

        return (neg)?-res:res; 

    }



const int maxN=200000;

const LL Mod=16777216;



int N;

int a[maxN+100];

LL l[maxN+100],r[maxN+100];

LL ans;



LL tree[maxN+100];

#define lowbit(a) (a&(-a))

inline void update(int a,LL v){for(;a<=N;a+=lowbit(a))tree[a]=(tree[a]+v)%Mod;}

inline LL ask(int a){LL res=0;for(;a>=1;a-=lowbit(a))res=(res+tree[a])%Mod;return res;}



LL g[maxN+100];



/*

 f(1324)-f(1243)-f(1432)

=f(1x2x)-f(1423)-f(12xx)+f(1234)-f(14xx)+f(1423)

=f(1x2x)+f(1234)-f(12xx)-f(14xx)

=f(1x2x)+f(1234)-[f(1xxx)-f(13xx)]

=f(1x2x)+f(13xx)+f(1234)-f(1xxx)

*/





int main()

  {

      freopen("bzoj1145.in","r",stdin);

      freopen("bzoj1145.out","w",stdout);

      int i;

      N=gint();

      re(i,1,N)a[i]=gint();

      mmst(tree,0);re(i,1,N)l[i]=ask(a[i]-1),update(a[i],1);

      mmst(tree,0);red(i,N,1)r[i]=ask(a[i]-1),update(a[i],1);

      ans=0;

      

      //+f(1x2x)

      re(i,1,N)g[i]=(LL(l[i])*LL(l[i]-1)/2+LL(l[i])*LL(i-1-l[i]))%Mod;

      mmst(tree,0);

      re(i,1,N)

        {

            g[i]=(g[i]-ask(a[i]-1))%Mod;

            update(a[i],i-1);

        }

      re(i,1,N)ans=(ans+g[i]*LL(N-i-r[i]))%Mod;

      

      //+f(13xx)

      mmst(tree,0);

      red(i,N,1)

        {

            LL t=LL(N-i-r[i]);

            LL p=(ask(a[i]-1)-r[i]*(r[i]-1)/2)%Mod;

            ans=(ans+p*t)%Mod;

            update(a[i],a[i]-1);

        }

         

      //+f(1234)

      re(i,1,N)g[i]=l[i];

      mmst(tree,0);re(i,1,N)update(a[i],g[i]),g[i]=ask(a[i]-1);

        mmst(tree,0);re(i,1,N)update(a[i],g[i]),g[i]=ask(a[i]-1);

        re(i,1,N)ans=(ans+g[i])%Mod;

        

        //-f(1xxx)

        re(i,1,N)

          {

              LL t=LL(N-i-r[i]);

              ans=(ans-t*(t-1)*(t-2)/6)%Mod;

            }

        

        ans=(ans%Mod+Mod)%Mod;

        cout<<ans<<endl;

        return 0;

    }
View Code

 

你可能感兴趣的:(ZOJ)