1372 - Hexagonal Bamboo Fort 树状数组

题目链接


给一个序列,查询可以组成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\n", ++kase, ans);
    }
    return 0;
}
posted @ 2017-09-08 19:12  可达龙  阅读(150)  评论(0编辑  收藏  举报