http://acm.hdu.edu.cn/showproblem.php?pid=4000
(1)核心算法:插入一个数 x ,求已插入的比 x 小的数的个数。
(2)核心数学知识:要求的满足 i<j<k && x<z<y 的(x, y, z)的组数。下面简写数学小知识:
x<z<y = x<y?z - x<y<z;
其中,y?z 表示 y, z 的大小没有确定。 更多的数学处理详见代码。
(3)考虑过更新时是update(a-1),还是update(a),这取决于更新和调用的顺序,顺序变了,代码自然变了一点点。这里附上代码2,一边比较。
(个人解题时的小错误)
(4)假如是 i<j<k && x<=z<=y(已知条件跟着变动),又该如何变动参数?(问题问得不清晰,露着以后找到了更符合的题目再来思考)。
具体代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include<stdio.h> #include<string.h> const int mxn=101000; int a, n, num[100010]; int lowbit(int x) { return x&(-x); } int sum(int x) { int s=0; while(x>0) { s+=num[x]; x-=lowbit(x); } return s; } void update(int x) { while(x<=n) { num[x]++; x+=lowbit(x); } } int main() { int i, j, k, t; while(~scanf("%d",&t)) { for(k=1;k<=t;k++) { scanf("%d", &n); memset(num, 0, sizeof(num)); __int64 ans=0; for(i=1;i<=n;i++) { scanf("%d", &a); int downl=sum(a); int up0=n-a; int upl=i-sum(a)-1; __int64 upr=up0-upl; ans-=downl*upr; ans+=upr*(upr-1)/2; update(a); } printf("Case #%d: %I64d\n", k, ans%100000007); } } return 0; }
比较代码(先更新):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include<stdio.h> #include<string.h> const int mxn=101000; int a, n, num[100010]; int lowbit(int x) { return x&(-x); } int sum(int x) { int s=0; while(x>0) { s+=num[x]; x-=lowbit(x); } return s; } void update(int x) { while(x<=n) { num[x]++; x+=lowbit(x); } } int main() { int i, j, k, t; while(~scanf("%d",&t)) { for(k=1;k<=t;k++) { scanf("%d", &n); memset(num, 0, sizeof(num)); __int64 ans=0; for(i=1;i<=n;i++) { scanf("%d", &a); update(a); int downl=sum(a-1); int up0=n-a; int upl=i-sum(a-1)-1; __int64 upr=up0-upl; ans-=downl*upr; ans+=upr*(upr-1)/2; } printf("Case #%d: %I64d\n", k, ans%100000007); } } return 0; }