HDU 2492

来源:互联网 发布:java连接ssh的jar包 编辑:程序博客网 时间:2024/06/08 18:33

这种有点小技巧的题目我都转不过弯,已然GG。考试的时候一直想着如何去算出2个点之间有多少个可以的裁判点,然而完全不好计数。就这样怼了一个半小时,其实转换一下,枚举裁判点,去统计能已该点为裁判点的左右两边的点对有多少,就很简单了,

x1是左边比该点搞的,x2是低的,x3是一样的,y1,y2,y3,则是右边的。

#include<cstdio>#include<cstring>#define maxl 100010int n;long long a[maxl],x1[maxl],x2[maxl],x3[maxl],y1[maxl],y2[maxl],y3[maxl];long long b[maxl];long long ans;void prework(){scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);}long long sum(int i){long long s=0;while(i){s+=b[i];i-=i&-i;}return s;}void add(int i,int x){while(i<maxl){b[i]+=x;i+=i&-i;}}void mainwork(){memset(b,0,sizeof(b));for(int i=1;i<=n;i++){x1[i]=sum(maxl-1)-sum(a[i]);x2[i]=sum(a[i]-1);x3[i]=sum(a[i])-sum(a[i]-1);add(a[i],1);}memset(b,0,sizeof(b));for(int i=n;i>=1;i--){y1[i]=sum(maxl-1)-sum(a[i]);y2[i]=sum(a[i]-1);y3[i]=sum(a[i])-sum(a[i]-1);add(a[i],1);}}void print(){ans=0;for(int i=1;i<=n;i++){ans+=x1[i]*(y2[i]+y3[i]);ans+=x2[i]*(y1[i]+y3[i]);ans+=x3[i]*y3[i]; }printf("%lld\n",ans);}int main(){int t;scanf("%d",&t);for(int i=1;i<=t;i++){prework();mainwork();print();}return 0;}


原创粉丝点击