题意:给定n个排成一排的信号灯以及每个的位置a[]和能量b[]。若第i信号灯被打开,那么在[a[i]-b[i], a[i]-1]范围里面的信号灯都会被破坏。若现在从右向左依次打开每个信号灯(坏的不能使用),问信号灯被破坏的最少数量。你需要在所有灯的右侧放置一个新的信号灯,位置和能量随意设置。
思路:先排下序,坑我一次。O__O "…。
设置一个状态——第i个灯没有被破坏且[i+1, n]范围的灯全部被破坏。
用dp[i]表示该状态下信号灯被破坏的最少数量。pos表示i灯可以影响到的最左侧的灯。
得到状态转移 dp[i] = dp[pos-1] + i - pos; 在转移的时候维护最优解即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (100000+10)
#define MAXM (500000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
struct Node{
int a, b;
};
Node num[MAXN];
bool cmp(Node A, Node B){
return A.a < B.a;
}
int dp[MAXN];
int Find(int l, int r, int val)
{
int ans = 0;
while(r >= l)
{
int mid = (l + r) >> 1;
if(num[mid].a >= val)
{
ans = mid;
r = mid-1;
}
else
l = mid+1;
}
return ans;
}
int main()
{
int n; Ri(n);
for(int i = 1; i <= n; i++)
Ri(num[i].a), Ri(num[i].b);
sort(num+1, num+n+1, cmp);
dp[0] = 0; int ans = INF;
for(int i = 1; i <= n; i++)
{
int pos = Find(1, n, num[i].a-num[i].b);
dp[i] = dp[pos-1] + i - pos;
ans = min(ans, dp[i]+n-i);
}
Pi(ans);
return 0;
}