#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int Max=20010; const int inf=100000; int lm[Max],rm[Max],a[Max],c[Max*10]; int n; long long lowbit(long long x) { return x&-x; } int sum(long long x,int *c) { int ret=0; while(x>0) { ret+=c[x]; x-=lowbit(x); } return ret; } void add(long long x,int d,int *c) { while(x<=inf) //从x到inf的数组都拥有一个小于等于x的数:x { c[x]+=d; x+=lowbit(x); } } int main() { int T; for(scanf("%d",&T);T;T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } memset(c,0,sizeof(c)); add(a[1],1,c); for(int i=2;i<=n;i++) { lm[i]=sum(a[i],c); add(a[i],1,c); } memset(c,0,sizeof(c)); add(a[n],1,c); for(int i=n-1;i>=1;i--) { rm[i]=sum(a[i],c); add(a[i],1,c); } long long ans=0; for(int i=1;i<=n;i++) { // cout<<i<<" lm: "<<lm[i]<<" rm: "<<rm[i]<<endl; ans+=lm[i]*(n-i-rm[i])+(i-1-lm[i])*rm[i]; } printf("%lld\n",ans); } return 0; }
题意:n个人,每个人都有一个能力值,每次举办比赛都要三个人,举办条件:
如果 i,j,k进行比赛时,如果k是裁判,必须要i<j<k(下标)而且ai<aj<ak(能力值)
思路:只要枚举每个人当裁判是他左边小于他的数个数lm和他右边小于他的数的个数rm
那么答案就是(左边总人数-lm)*(rm)+(lm)*(右边总人数-rm)
如果对每个lm和rm进行枚举的话那么时间会是n^2
可以对树状数组的add操作加以改变,将从ci数组定以为此时ai出现之前的小于ai的数的个数
动态加一,然后求1到ai的sum值
时间: 2024-12-12 22:55:31