一、题目
二、解法
考试时候想的太抽象了,不知道这题是推柿子(顺便说一下,二分是没有用的)
首先要抓关键点:机器人永远只会在糖果的位置和时间上。我们考虑机器人在一段时间内的运动,所以这一点是显然的。那么我们考虑推第
i
i
i 颗糖果可以到第
j
j
j 颗糖果时需要满足的柿子:
∣
s
i
−
s
j
∣
≤
t
j
−
t
i
|s_i-s_j|\leq t_j-t_i
∣si−sj∣≤tj−ti然后结合我们学过的绝对值不等式可以推出:
t
i
−
s
i
≤
t
j
−
s
j
,
t
i
+
s
i
≤
t
j
+
s
j
t_i-s_i\leq t_j-s_j,t_i+s_i\leq t_j+s_j
ti−si≤tj−sj,ti+si≤tj+sj完了,就是一个二维偏序问题,我们要选出最少的子序列使其包含整个序列并且子序列内部满足此偏序关系,我们先按
t
i
+
s
i
t_i+s_i
ti+si 排序,然后用
s
e
t
\tt set
set 可以维护现存子序列的结尾,我们选出一个满足条件且值最大的结尾接上(不难理解的贪心),否则新加入一个子序列即可。
你没发现就是 导弹拦截 么
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
const int M = 100005;
#define pii pair<int,int>
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,ans[M];set<pii> s;
struct node
{
int a,b,x,y;
bool operator < (const node &b) const
{
if(x==b.x) return y<b.y;
return x<b.x;
}
}p[M];
int main()
{
freopen("candy.in","r",stdin);
freopen("candy.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)
{
int b=read(),a=read();
p[i]=node{b,a,a+b,a-b};
}
sort(p+1,p+1+n);
for(int i=1;i<=n;i++)
{
if(s.empty())
{
s.insert(make_pair(p[i].y,++m));
ans[i]=m;continue;
}
set<pii>::iterator it=s.upper_bound(make_pair(p[i].y,n+1));//这里pair排序要注意
if(it==s.begin())
{
s.insert(make_pair(p[i].y,++m));
ans[i]=m;continue;
}
it--;
ans[i]=(*it).second;
s.erase(it);
s.insert(make_pair(p[i].y,ans[i]));
}
printf("%d\n",m);
for(int i=1;i<=n;i++)
printf("%d %d %d\n",p[i].a,p[i].b,ans[i]);
}