调了半天都是10分,求调

P4799 [CEOI2015 Day2] 世界冰球锦标赛

Furinaaaa @ 2024-07-07 17:15:23


#define _CRT_SECURE_NO_WARNINGS

using namespace std;

#include <iostream>

typedef unsigned long long U;

const int M = 1e8 + 6;

U n, m, mid;

U a[114514];

//前一半的票价
U p1[M];
U n1 = 0;

//后一半的票价
U p2[M];
U n2 = 0;

//计算前一半的票价
void dfs1(U i, U money)
{
    //剪枝
    if (money > m)
    {
        return;
    }
    //出口
    if (i > mid)
    {
        p1[n1] = money;
        n1 += 1;
        return;
    }
    //剪枝
    if (money > m)
    {
        return;
    }
    //正常情况
    dfs1(i + 1, money);
    dfs1(i + 1, money + a[i]);

}

//计算后一半的票价
void dfs2(U i, U money)
{
    //剪枝
    if (money > m)
    {
        return;
    }
    //出口
    if (i > n)
    {
        p2[n2] = money;
        n2 += 1;
        return;
    }

    //正常情况
    dfs2(i + 1, money);
    dfs2(i + 1, money + a[i]);

}

//排序
int cmp(const void* a, const void* b)
{
    U* aa;
    U* bb;
    aa = (U*)a;
    bb = (U*)b;
    if (*aa > *bb)
    {
        return 1;
    }
    if (*aa == *bb)
    {
        return 0;
    }
    return -1;
}

int main()
{
    cin >> n >> m;
    mid = n / 2;
    for (U i = 1; i <= n; i++)
    {
        cin >> a[i];
    }

    dfs1(1, 0);
    dfs2(mid + 1, 0);
    qsort(p2, n2, sizeof(U), cmp);

    U ans = 0;
    //遍历p1,只要小于就加
    for (int i = 0; i < n1; i++)
    {
        U l, r, mid1 , j;
        l = 0;
        r = n2;
        j = 0 ; 
        mid1 = (l + r) / 2;
        if (p1[i] + p2[n2-1] <= m )
        {
            ans += n2;
            continue;
        }
        while (1)
        {
            //出口
            if (l >= r)
            {
                break;
            }
            if (p2[mid1] + p1[i] <= m)
            {
                //不超过总数
                //贪心,希望尽可能地大一点
                //mid1可以成为答案,移动时保留
                l = mid1;
                j = 1 ; 
            }
            else
            {
                //超过,绝对不能要
                r = mid1 - 1;
            }
            mid1 = (l + r) / 2 + 1;
        }
        if (j)
        {
            ans += l + 1;
        }

    }
    cout << ans;
    return 0;

}

by Furinaaaa @ 2024-07-08 09:33:39

AC了,警钟长鸣,r=n2改成r=n2-1就行了


#define _CRT_SECURE_NO_WARNINGS

using namespace std;

#include <iostream>

typedef unsigned long long U;

const int M = 1e8 + 6;

U n, m, Mid;

U a[114514];

//前一半的票价
U p1[M];
U n1 = 0;

//后一半的票价
U p2[M];
U n2 = 0;

//计算前一半的票价
void dfs1(U i, U money)
{
    //剪枝
    if (money > m)
    {
        return;
    }
    //出口
    if (i > Mid)
    {
        p1[n1] = money;
        n1 += 1;
        return;
    }
    //剪枝
    if (money > m)
    {
        return;
    }
    //正常情况
    dfs1(i + 1, money);
    dfs1(i + 1, money + a[i]);

}

//计算后一半的票价
void dfs2(U i, U money)
{
    //剪枝
    if (money > m)
    {
        return;
    }
    //出口
    if (i > n)
    {
        p2[n2] = money;
        n2 += 1;
        return;
    }

    //正常情况
    dfs2(i + 1, money);
    dfs2(i + 1, money + a[i]);

}

//排序
int cmp(const void* a, const void* b)
{
    U* aa;
    U* bb;
    aa = (U*)a;
    bb = (U*)b;
    if (*aa > *bb)
    {
        return 1;
    }
    if (*aa == *bb)
    {
        return 0;
    }
    return -1;
}

int main()
{
    cin >> n >> m;
    Mid = n / 2;
    for (U i = 1; i <= n; i++)
    {
        cin >> a[i];
    }

    dfs1(1, 0);
    dfs2(Mid + 1, 0);
    qsort(p2, n2, sizeof(U), cmp);

    U ans = 0;
    //遍历p1,只要小于就加
    for (int i = 0; i < n1; i++)
    {
        U l , r , mid , need , real ;
        l = 0 ;
        real = 0 ; 
        r = n2 - 1 ; 
        mid = r / 2 ; 
        need = m - p1[i] ;
        //不可能
        if (need < 0)
        {
            continue ; 
        }
        while (1)
        {
            if (l >= r)
            {
                break ; 
            }
            if (p2[mid] <= need)
            {
                real = mid ; 
                l = mid ;
            }
            else
            {
                r = mid - 1 ; 
            }
            mid = ( l + r ) /2 + 1 ; 
        }

        ans += real + 1 ; 
    }
    cout << ans;
    return 0;

}

|