CodeForces - 76F:Tourist (旋转坐标系,LIS)
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; }
It is your time to fight!