Description

你曾经梦想过你是电脑游戏中的主角吗?这个故事的主角,Branimir,现在正在做这个梦。
在Branimir的梦中,世界是由从左到右排列的N座摩天大楼组成的。对于第i座摩天大楼,我们知道摩天大楼的高度Hi和房顶金币的数量Gi。游戏从在任何摩天大楼上跳跃开始,由几步组成。在每一步中,Branimir都可以从他目前所在的摩天大楼向右跳(他也有可能跳过其中的几个),到一个高度不低于现在的摩天大楼。假如Branimir在一座摩天大楼,他可以拿这座大楼的金币。Branimir可以在任意步数之后结束游戏(0步也可以)通往下一关,但必须要收集至少K个金币。
现在要求Branimir通往下一关的方案数。两个方案当做不同当且仅当Branimir在其中一次跳过其中一座摩天大楼而另一次没有。

Input

第一行包含两个整数n,K
接下来n行,每行两个整数Hi和Gi

Output

输出一个整数,表示不同的方案数。

Sample Input

input1:
4 6
2 1
6 3
7 2
5 6
input2:
2 7
4 6
3 5
input3:
4 15
5 5
5 12
6 10
2 1

Sample Output

output1:
3
output2:
0
output3:
4

Data Constraint

对于40%的数据,1<=n<=20
对于100%的数据,1<=n<=40,1<=k<=4*10^10,1<=Hi,Gi<=10^9

Hint

第一个样例解释
{1,2,3},{1,4}{4}三种方案

思路

正解

折半搜索

我们先搜出前面一半,存下他的两个信息(sl,hl),sl 是前面的金币和,hl 是最右端的点的高度。
我们先搜出后面一半,存下他的两个信息(sr,hr),sr 是后面的金币和,hr 是最左端的点的高度。

现在相当于找满足 sl+sr>=k,hl<=hr 的二元组的对数。

我们把 hl 相同的按照 sl 从小到大排序。

然后枚举二元组(sr,hr),接着枚举 hl(hl<=hr),然后就相当于求 sr+sl>=k 的个数,由于已经排序,sl 有序,所以后面只需要二分就行了。

水法

数据太水了
我用了A*+决策性剪枝就过了

水法代码
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=107;
long long ans=0,k,f[maxn],h[maxn],g[maxn];
int n,cnt,list[maxn],hi[maxn];
struct E
{
    int to,next;
}e[maxn*maxn];
void add(int u,int v)
{
    e[++cnt].to=v; e[cnt].next=list[u]; list[u]=cnt;
}
long long get_h(int u)
{
    long long s=g[u];
    for(int i=list[u]; i; i=e[i].next) s=max(s,g[u]+h[e[i].to]);
    return s;
}
long long get_f(int u)
{
    long long s=1;
    for(int i=list[u]; i; i=e[i].next) s+=f[e[i].to];
    return s;
}
void dfs(int u,long long x)
{
    if(x>=k)
    {
        ans+=f[u]; return;
    }
    if(x+h[u]-g[u]<k) return;
    for(int i=list[u]; i; i=e[i].next)
    {
        int v=e[i].to;
        dfs(v,x+g[v]);
    }
    return;
}
int main()
{
    freopen("san.in","r",stdin); freopen("san.out","w",stdout);
    scanf("%d%lld",&n,&k);
    for(int i=1; i<=n; i++) scanf("%d%lld",&hi[i],&g[i]);
    for(int i=1; i<n; i++)
    {
        for(int j=i+1; j<=n; j++) if(hi[i]<=hi[j]) add(i,j);
    }
    f[n]=1; h[n]=g[n];
    for(int i=n-1; i>=1; i--) h[i]=get_h(i),f[i]=get_f(i);
    for(int i=1; i<=n; i++) dfs(i,g[i]);
    printf("%lld",ans);
    return 0;
}