1. 程式人生 > >UVA1428 【Ping pong】乒乓球

UVA1428 【Ping pong】乒乓球

題意:一條大街上住著n個乒乓球愛好者,經常組織比賽切磋技術。每個人都有一個不同的技能值a[i]。每場比賽需要3個人:兩名選手,一名裁判。他們有一個奇怪的規定,即裁判住在兩名選手中間,並且技能值也在兩名選手之間。問一共能組織多少種比賽。

解法:設a[1]->a[i-1]有c[i]個比a[i]小;設a[i+1]->a[n]有d[i]個比a[i]大;對於i來說c[i]*(n-i-d[i])+d[i]*(i-c[i]-1)。

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
4 long long int a[200005],c[200005],d[200005],s[200005]; 5 long long int max1; 6 long long int lowbit(long long int x) 7 { 8 return x&-x; 9 } 10 long long int sum(long long int x) 11 { 12 int ret=0; 13 while(x>0) 14 { 15 ret+=c[x]; 16 x-=lowbit(x); 17 } 18 return ret; 19 20
} 21 void add(long long int x,int d1) 22 { 23 while(x<=max1) 24 { 25 c[x]+=d1; 26 x+=lowbit(x); 27 } 28 } 29 int main() 30 { 31 int n,t; 32 max1=-1; 33 cin>>t; 34 while(t--) 35 { 36 cin>>n; 37 for(int i=1;i<=n;i++) 38 {
39 cin>>a[i]; 40 max1=(max1>a[i])?max1:a[i]; 41 } 42 memset(c,0,sizeof(c)); 43 for(int i=1;i<=n;i++) 44 { 45 s[i]=sum(a[i]); 46 add(a[i],1); 47 } 48 memset(c,0,sizeof(c)); 49 for(int i=n;i>=1;i--) 50 { 51 d[i]=sum(a[i]); 52 add(a[i],1); 53 } 54 long long int cnt=0; 55 for(int i=1;i<=n;i++) 56 { 57 cnt+=(s[i]*(n-i-d[i])+(i-1-s[i])*d[i]); 58 } 59 cout<<cnt<<endl; 60 } 61 return 0; 62 }