POJ 3928 Ping pong

来源:互联网 发布:sql 分组求和 编辑:程序博客网 时间:2024/05/19 18:44

题目大意:

        给定一个序列,保证序列中的元素互不相等,且元素的范围为[1, 100000],然后找出三元组的个数,三元组为(ai, aj, ak), i < j < k, ai < aj < ak或ai > aj > ak,其中元素个数N不超过20,000个。

        现有多个测例(测例数题中给出),每个测例都给出N和各元素,要求输出指定三元组个数(个数可能会超出int范围,因此要用__int64)。

题目链接

注释代码:

/*                                               * Problem ID : POJ 3928 Ping pong * Author     : Lirx.t.Una                                               * Language   : C                              * Run Time   : 313 ms                                               * Run Memory : 836 KB                                              */  #include <memory.h>#include <stdlib.h>#include <stdio.h>//maximum number of palyers//球手的最大数量#defineMAXPYN20001//maximum skill rank//球手的最大能力值#defineMAXRANK100001#defineLOWBIT(x)( (x) & (-x) )#defineINC(x)( (x) += LOWBIT((x)) )#defineDEC(x)( (x) -= LOWBIT((x)) )typedef__int64llg;shortlft_tree[MAXPYN];//对原数组从左往右建立BITshortrht_tree[MAXPYN];//对原数组从右往左建立BITinta[MAXPYN];//保存原数组,即球员的能力值intaa[MAXPYN];//用于复制原数组,并对原数组进行离散化//这样可以减小BIT的规模,减少INC和DEC的次数,从而减小时间复杂度和空间复杂度intmp[MAXRANK];//建立对a对离散值的映射mp[ a[x] ] = discrete xshortblft[MAXPYN];//left to i and below a[i],即位于i左边且值比i小的元素个数(在原数组中)shortbrht[MAXPYN];//位于i右侧的shortsum( short *tree, int x ) {//求1 ~ x区间的和(BIT内)//直接将元素中的值映射到了BIT的下标//BIT的下标一定是从1开始,因为LOWBIT是二分而得的!!shortres;res = 0;while ( x > 0 ) {res += tree[x];DEC(x);}return res;}voidadd( short *tree, int x, int n ) {//向BIT中添加x元素while ( x <= n ) {tree[x]++;INC(x);}}intfcmp(const void *a, const void *b) {//用于排序,用于离散化return *(int *)a - *(int *)b;}intmain() {intt;//测例数intn;//球手数量inti, j;//计数变量intx;//临时变量llgans;scanf("%d", &t);while ( t-- ) {scanf("%d", &n);for ( i = 1; i <= n; i++ ) scanf("%d", a + i);memcpy(aa, a, sizeof(aa));qsort(aa + 1, n, sizeof(int), &fcmp);for ( j = 1, i = 1; i <= n; i++, j++ ) {mp[ aa[i] ] = j;while ( i < n && aa[i] == aa[i + 1] ) i++;}j--;//离散化完毕memset(lft_tree, 0, sizeof(lft_tree));memset(rht_tree, 0, sizeof(rht_tree));for ( i = 1; i <= n; i++ ) {x = mp[ a[i] ];blft[i] = sum( lft_tree, x - 1 );add( lft_tree, x, j );}for ( i = n; i >= 1; i-- ) {x = mp[ a[i] ];brht[i] = sum( rht_tree, x - 1 );add( rht_tree, x, j );}//位于i右边且比i大的个数为( n - i - brht[i] )//位于i左边且比i大的个数为( i - 1 - blft[i] )for ( ans = 0, i = 1; i <= n; i++ )ans += (llg)blft[i] * (llg)( n - i - brht[i] ) +   (llg)( i - 1 - blft[i] ) * (llg)brht[i];printf("%I64d\n", ans);}return 0;}

无注释代码:

#include <memory.h>#include <stdlib.h>#include <stdio.h>#defineMAXPYN20001#defineMAXRANK100001#defineLOWBIT(x)( (x) & (-x) )#defineINC(x)( (x) += LOWBIT((x)) )#defineDEC(x)( (x) -= LOWBIT((x)) )typedef__int64llg;shortlft_tree[MAXPYN];shortrht_tree[MAXPYN];inta[MAXPYN];intaa[MAXPYN];intmp[MAXRANK];shortblft[MAXPYN];shortbrht[MAXPYN];shortsum( short *tree, int x ) {shortres;res = 0;while ( x > 0 ) {res += tree[x];DEC(x);}return res;}voidadd( short *tree, int x, int n ) {while ( x <= n ) {tree[x]++;INC(x);}}intfcmp(const void *a, const void *b) {return *(int *)a - *(int *)b;}intmain() {intt;intn;inti, j;intx;llgans;scanf("%d", &t);while ( t-- ) {scanf("%d", &n);for ( i = 1; i <= n; i++ ) scanf("%d", a + i);memcpy(aa, a, sizeof(aa));qsort(aa + 1, n, sizeof(int), &fcmp);for ( j = 1, i = 1; i <= n; i++, j++ ) {mp[ aa[i] ] = j;while ( i < n && aa[i] == aa[i + 1] ) i++;}j--;memset(lft_tree, 0, sizeof(lft_tree));memset(rht_tree, 0, sizeof(rht_tree));for ( i = 1; i <= n; i++ ) {x = mp[ a[i] ];blft[i] = sum( lft_tree, x - 1 );add( lft_tree, x, j );}for ( i = n; i >= 1; i-- ) {x = mp[ a[i] ];brht[i] = sum( rht_tree, x - 1 );add( rht_tree, x, j );}for ( ans = 0, i = 1; i <= n; i++ )ans += (llg)blft[i] * (llg)( n - i - brht[i] ) +   (llg)( i - 1 - blft[i] ) * (llg)brht[i];printf("%I64d\n", ans);}return 0;}

单词解释:

contestant:n, 竞争者

referee:n, 裁判

line segment:n, 线段

0 0
原创粉丝点击