P4799 [CEOI 2015] 世界冰球锦标赛 (Day2)(双向广搜/折半搜索)

题目链接:https://www.luogu.com.cn/record/226316667

思路

首先观察数据量可知,1018的数据量,不可以直接使用动态规划来做,所以考虑使用dfs来做,如果直接使用dfs,当n为40时,情况有240种可能,同样过大,这时候我们可以考虑将数组拆成两半,最终使用双指针来计算总方案数,这样的话,左边和右边各只有220种可能,最后使用双指针也只需要220次计算,所以最后的时间复杂度能过此题

题解

#include <bits/stdc++.h>
using namespace std;
const int N=1<<21;
typedef long long ll;
int t,n;
ll m;
ll a[N];
ll lsum[N];
ll rsum[N];

int f(int l,int r,ll *arr,ll sum,int sz)
{
    if(sum>m)return sz;
    if(l==r)arr[sz++]=sum;
    else
    {
        sz = f(l+1,r,arr,sum+a[l],sz);
        sz = f(l+1,r,arr,sum,sz);
    }
    return sz;
}


int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i=0;i<n;i++)cin>>a[i];
    int lsz = f(0,n>>1,lsum,0,0);
    int rsz = f(n>>1,n,rsum,0,0);
    sort(lsum,lsum+lsz);
    sort(rsum,rsum+rsz);

    // for(int i=0;i<lsz;i++)cout<<lsum[i]<<' ';
    // cout<<endl;
    // for(int i=0;i<rsz;i++)cout<<rsum[i]<<' ';
    // cout<<endl;

    ll ans=0;
    for(int i=lsz-1,j=0;i>=0;i--)
    {
        while(j<rsz&&lsum[i]+rsum[j]<=m)
        {
            j++;
        }
        ans+=j;
    }
    cout<<ans<<endl;

    return 0;
}
posted @ 2025-07-23 15:40  屈臣  阅读(6)  评论(0)    收藏  举报