Codeforces Round #336 (Div. 2) C 二分+dp

CrossDolphin發表於2016-07-08



連結:戳這裡


C. Chain Reaction
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
There are n beacons located at distinct positions on a number line. The i-th beacon has position ai and power level bi. When the i-th beacon is activated, it destroys all beacons to its left (direction of decreasing coordinates) within distance bi inclusive. The beacon itself is not destroyed however. Saitama will activate the beacons one at a time from right to left. If a beacon is destroyed, it cannot be activated.

Saitama wants Genos to add a beacon strictly to the right of all the existing beacons, with any position and any power level, such that the least possible number of beacons are destroyed. Note that Genos's placement of the beacon means it will be the first beacon activated. Help Genos by finding the minimum number of beacons that could be destroyed.

Input
The first line of input contains a single integer n (1 ≤ n ≤ 100 000) — the initial number of beacons.

The i-th of next n lines contains two integers ai and bi (0 ≤ ai ≤ 1 000 000, 1 ≤ bi ≤ 1 000 000) — the position and power level of the i-th beacon respectively. No two beacons will have the same position, so ai ≠ aj if i ≠ j.

Output
Print a single integer — the minimum number of beacons that could be destroyed if exactly one beacon is added.

Examples
input
4
1 9
3 1
6 1
7 4
output
1
input
7
1 1
2 1
3 1
4 1
5 1
6 1
7 1
output
3
Note
For the first sample case, the minimum number of beacons destroyed is 1. One way to achieve this is to place a beacon at position 9 with power level 2.

For the second sample case, the minimum number of beacons destroyed is 3. One way to achieve this is to place a beacon at position 1337 with power level 42.


題意:

給出n個遊標,放在x軸上,每個遊標有一個啟用裝置,啟用之後能把左邊ai範圍內的遊標全炸了

現在要求你在所有遊標的最右邊安放一個遊標,使的摧毀的遊標最少。注意遊標會從右往左一一啟用

啟用的遊標在炸了右邊的遊標之後本身不會被摧毀


思路:

對於每個遊標,相當於把一個線段[l,r]鋪在x軸上,然後拿掉最少數量的遊標使得線段不重複

那麼就是對n個區間[l,r]進行取捨的問題了,我們先按區間的r排個序

接下來我們設定dp[]狀態表示當前第i個區間作為最後一個遊標的最優值(也就是儲存的遊標數量最大)

那麼當前遊標能影響的遊標也就是[1,i-1]裡面能覆蓋的個數,用二分找到當前i能覆蓋的最遠距離(也就是最遠的rj 1<=j<=i-1)

減去最遠距離到i的遊標個數,在取dp[mid]+1  更新最大的ans


程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
int n;
struct node{
    int l,r;
}s[100100];
bool cmp(node a,node b){
    if(a.r==b.r) return a.l<b.l;
    return a.r<b.r;
}
int dp[1000100];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int x,rang;
        scanf("%d%d",&x,&rang);
        s[i].l=x-rang;
        s[i].r=x;
    }
    sort(s+1,s+n+1,cmp);
    dp[0]=1;
    s[0].l=-1000000000;
    s[0].r=-1000000000;
    int ans=0;
    for(int i=1;i<=n;i++){
        int l=0,r=i-1,mid,f=-1;
        while(l<=r){
            mid=(l+r)/2;
            if(s[mid].r<s[i].l) {
                l=mid+1;
                f=mid;
            }
            else if(s[mid].r==s[i].l) r=mid-1;
            else r=mid-1;
        }
        dp[i]=dp[f]+1;
        ans=max(ans,dp[i]);
    }
    cout<<n+1-ans<<endl;
    return 0;
}



相關文章