小 Z 最近买了很多很多的多米诺骨牌,他选出了其中的一些排成了一排,并
且准备从右到左碰倒这些骨牌。 每个骨牌有一个坐标xi(>=1)和一个大小yi(>=1),
倒下时将会碰倒坐标区间位于[xi-yi,xi)内的所有骨牌。当然没有两个骨牌有相同
的坐标,并且小 Z 规定坐标大的更靠右。
但是他发现他买的骨牌太巨了,所以在倒下的时候会将所有碰倒的骨牌破坏
掉,被破坏掉的骨牌就无法使用了,并且不会倒下。得知这个消息的小 Z 十分惊
讶,他想知道如果还按刚才这种方法从右到左碰倒所有没被破坏的骨牌, 将有多
少个骨牌被破坏。这个问题对你来说太简单啦,所以小 Z 又改了主意,他现在想
知道,如果他可以在所有骨牌的严格右边任意位置放置一个任意大小的骨牌, 最
少有多少个骨牌会被破坏?
[输入格式]
从 card.in 中读取数据。
第一行读入一个数字 n,表示小 Z 已经摆放的骨牌数量。
接下来 n 行,每行读入两个正数 xi,yi,表示一个骨牌的信息。
[输出格式]
输出一个数字,表示最少有多少个骨牌被破坏。
[样例输入]
4
1 9
3 1
6 1
7 4
[样例输出]
1
[样例解释]
假如在位置 666 摆放一个大小 659 的骨牌,将会只有一个骨牌被破坏。
[数据范围与约定]
对于 20%的数据 保证存在一个最优方案在坐标[1,100]内摆放骨牌
对于 40%的数据 n<=5000
对于 100%的数据 n<=100000,1<=xi,yi<=10^9
二分每一块骨牌倒下后左端的位置,然后从倒下的位置转移到当前位置。
#include<cstdio> #include<algorithm> using namespace std; int n; int f[100001]; int x[100001],y[100001],num[100001],c[100001]; bool cmp(int p,int q){ return x[p]<x[q]; } int ans; int main(){ //freopen("card.in","r",stdin); //freopen("card.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&x[i],&y[i]);num[i]=i; } sort(num+1,num+n+1,cmp); for(int i=1;i<=n;i++) c[i]=x[num[i]]; for(int i=2;i<=n;i++){ int loc=lower_bound(c+1,c+n+1,x[num[i]]-y[num[i]])-c-1; f[i]=f[loc]+i-loc-1; } int ans=n; for(int i=2;i<=n;i++){ if(f[i]+n-i<ans) ans=f[i]+n-i; } printf("%d\n",ans); return 0; }