给一个序列,查询可以组成6边形的选择方式。
思路:
组成条件是(a_1<a_2<a_3<a_4<a_5<a_6 \,\, AND\,\, a_1+a_2+a_3+a_4+a_5 > a_6)
想过优化(a_1+a_2+a_3 > a_6-a_5-a_4),枚举(a_3)或者(a_4),但是这样仍是O((n^4)),仍是不行的。
参考了别人的方法,对于(a_3)和(a_4)的选择,只需要选择一个,另一个的范围就已经确定了,这样就变成O((n^3)).
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <math.h>
#include <bitset>
#include <ctype.h>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-9;
const int N = 1e6 + 5;
const int mod = 1e9 + 7;
int n,t,kase=0;
int c[N],a[N];
inline int lowbit(int x)
{
return x&(-x);
}
void add(int x, int val)
{
while(x < N)
{
c[x] += val;
x += lowbit(x);
}
}
int sum(int x)
{
int sum = 0;
while(x)
{
sum += c[x];
x -= lowbit(x);
}
return sum;
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
sort(a, a+n);
memset(c, 0, sizeof(c));
LL ans = 0;
for(int k = n-1; k >= 0; k--)
{
for(int i = 0; i < k; i++)
{
for(int j = i+1; j < k; j++)
{
int tmp = a[i]+a[j]+a[k];
ans += sum(tmp-1);
}
}
for(int i = k+1; i < n; i++)
{
for(int j = i+1; j < n; j++)
{
int tmp = a[j]-a[i]-a[k];
if(tmp <= 0) tmp = 1;
add(tmp, 1);
}
}
}
printf("Case %d: %lld
", ++kase, ans);
}
return 0;
}