pro:有一个驴友,以及给定N个表演地点xi和时间ti,驴友的速度不能超过V。 问他在起点为原点和不设置起点的情况下分别最多参观多少个表演。 

sol:BZOJ接飞饼见过;clari也在camp的DP专题讲过。  大概是解决这样一类问题,给定N个点,以及一种不等式关系,可以转化为二维平面上的点,然后按照某一维排序,第二维求LIS。(注意是这里的二维坐标不一定是标准的坐标)。 

 这里不难找到不等式:如果i之后可以访问j,则有|xj-xi|<=V*(tj-ti);这样的话转化为二维关系:

   xi+v*ti<=xj+v*tj;   -xi+vti<=-xj+v*tj;

然后求LIS即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
struct in{
    ll x,y;
    friend bool operator <(in w,in v){
        if(w.x==v.x) return w.y<v.y;
        return w.x<v.x;
    }
}s[maxn];
ll a[maxn],x[maxn],t[maxn],V; int ans1,ans2;
int main()
{
    int N,tot,pos;
    scanf("%d",&N);
    rep(i,1,N) scanf("%lld%lld",&x[i],&t[i]);
    scanf("%lld",&V);
    rep(i,1,N) s[i].x=x[i]+t[i]*V,s[i].y=-x[i]+t[i]*V;
    sort(s+1,s+N+1);
    tot=0;
    rep(i,1,N) {
        pos=upper_bound(a+1,a+tot+1,s[i].y)-a;
        a[pos]=s[i].y;
        if(pos>tot) tot=pos;
    }
    ans1=tot;
    tot=0;
    rep(i,1,N) {
        if(s[i].x<0||s[i].y<0) continue;
        pos=upper_bound(a+1,a+tot+1,s[i].y)-a;
        a[pos]=s[i].y;
        if(pos>tot) tot=pos;
    }
    ans2=tot;
    printf("%d\n%d\n",ans2,ans1);
    return 0;
}