现在的位置: 首页 > 综合 > 正文

CF 76F Tourist(最长不递减子序列变形)

2012年06月28日 ⁄ 综合 ⁄ 共 2771字 ⁄ 字号 评论关闭
F. Tourist
time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Tourist walks along the X axis. He can choose either of two directions and any speed not exceeding V.
He can also stand without moving anywhere. He knows from newspapers that at time t1 in
the point with coordinate x1 an
interesting event will occur, at time t2 in
the point with coordinate x2 —
another one, and so on up to (xn, tn).
Interesting events are short so we can assume they are immediate. Event icounts visited if at time ti tourist
was at point with coordinate xi.

Write program tourist that will find maximum number of events tourist if:

  • at the beginning (when time is equal to 0) tourist appears at point 0,
  • tourist can choose initial point for himself.

Yes, you should answer on two similar but different questions.

Input

The first line of input contains single integer number N (1 ≤ N ≤ 100000)
— number of interesting events. The following N lines contain two integers xi and ti —
coordinate and time of the i-th event. The last line of the input contains integer V —
maximum speed of the tourist. All xi will
be within range  - 2·108 ≤ xi ≤ 2·108,
all ti will be
between 1 and 2·106 inclusive. V will
be positive and will not exceed 1000. The input may contain events that happen at the same time or in the same place but not in the same place at the same time.

Output

The only line of the output should contain two space-sepatated integers — maximum number of events tourist can visit in he starts moving from point 0 at time 0, and maximum number of events tourist can visit if he chooses the initial point for himself.

Sample test(s)
input
3
-1 1
42 7
40 8
2
output
1 2

题目:http://codeforces.com/problemset/problem/76/F

题意:给你n个事件发生的事件和地点,在一条直线上,求最多可以见到几个事件。。。

分析:最直接的想法就是按时间排序,之后就可以简单的DP,这样明显是超时的,这种情况下,我们就得换种排序方式来改变数据的序,也改变转移方程。。。

一个点可以到达另一个点有个条件 abs(x[i]-x[j])<=abs(t[i]-t[j])*v

而这个不等式可以转换为 -x[ i ]+t[ i ]*v<=-x[ j ]+t[ j ]*v&&x[ i ]+t[ i ]*v<=x[ j ]+t[ j ]*v,为什么呢?

我们先假设t[ i ]<=t[ j ],那么有 A:x[ i ]-x[ j ]<=(t[ j ]- t[ i ])*v (x[ i ]>=x[ j ])  B: x[ j ]-x[ i ]<=(t[ j ]- t[ i ])*v (x[ i ]<x[ j ])

仔细琢磨,发现x[ i ]>=x[ j ]的时候,有B式子一定满足,相反的A一定满足,所有只要AB同时满足,就说明可以到达

而t[ i ]> t[ j ]的情况与上面的情况类似,最后就推出上面的不等式。。。

知道上面的关系后,把每个事件,变成两个变量,a=-x[i ]+t[i]*v  b=x[i]+t[i]*v

按a排序,如果a相同,按b排序。。。然后就是LIS问题了

PS:高中没认真学数学,看来我真的错了T_T

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int mm=111111;
struct data
{
    long long p,q;
}g[mm];
long long q[mm],x[mm],t[mm],v;
int i,j,n,r,ans;
bool cmp(data a,data b)
{
    return a.p<b.p||(a.p==b.p&&a.q<b.q);
}
int find(int l,int r,long long x)
{
    int m,ret=0;
    while(l<=r)
    {
        m=(l+r)>>1;
        if(q[m]>x)ret=m,r=m-1;
        else l=m+1;
    }
    return ret;
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(i=0;i<n;++i)
            scanf("%I64d%I64d",&x[i],&t[i]);
        scanf("%I64d",&v);
        for(i=0;i<n;++i)
        {
            g[i].p=-x[i]+t[i]*v;
            g[i].q=x[i]+t[i]*v;
        }
        sort(g,g+n,cmp);
        q[0]=-1e12,q[r=1]=1e12;
        for(i=0;i<n;++i)
        {
            j=find(0,r,g[i].q);
            if(q[j]>g[i].q)q[j]=g[i].q;
            if(j>=r)q[++r]=1e12;
        }
        ans=r-1;
        q[r=1]=1e10;
        for(i=0;i<n;++i)
            if(g[i].p>=0&&g[i].q>=0)
            {
                j=find(0,r,g[i].q);
                if(q[j]>g[i].q)q[j]=g[i].q;
                if(j>=r)q[++r]=1e12;
            }
        printf("%d %d\n",r-1,ans);
    }
    return 0;
}

抱歉!评论已关闭.