题目
输出序列中有多少个组合 { a1,a2,a3,a4,a5,a6}可以构成一个六边形。
分析
序列每个数都不相等。
所以可以设 a1<a2<a3<a4<a5<a6。 把六边形分解为 4 个三角形, 又可以得出 a1+a2+a3+a4+a5>a6: a1+a2+a3>a6−a5−a4。 在 a4 固定的情况下, a3可以取[a3,a4)之间 所以我们枚举 , 用树状数组维护。Code
#includeusing namespace std;const int maxn = 5000000 + 131;int C[maxn];int lowbit(int x) { return x &(-x);}int Sum(int x) { int ret = 0; while(x) { ret += C[x]; x -= lowbit(x); } return ret;}void Add(int pos) { while(pos < maxn) { C[pos] ++; pos += lowbit(pos); }}int Num[105];int main() { int T; scanf("%d",&T); for(int kase = 1; kase <= T; ++kase) { memset(C, 0, sizeof(C)); int N; scanf("%d",&N); for(int i = 0; i < N; ++i) scanf("%d",Num+i); sort(Num, Num+N); int Ans = 0, LowZ = 0; //小于0的情况用LowZ 统计 for(int i = N-1; i >= 0; --i) { for(int j = 0; j < i; ++j) for(int k = j+1; k < i; ++k) { int sum = Num[i] + Num[j] + Num[k]; Ans += Sum(sum-1); Ans += LowZ; } for(int j = i + 1; j < N; ++j) for(int k = j + 1; k < N; ++k) { int sub = Num[k] - Num[j] - Num[i]; if(sub > 0) Add(sub); else LowZ ++; } } printf("Case %d: %d\n",kase, Ans); } return 0;}