Acwing 295.清理班次 (数据结构优化DP)

题目

农民约翰正在指挥他的N头牛进行清理工作。

他将一天划分为了T个班次(1~T)。

每头牛都只能在一天中的某一个时间段内进行不间断的工作。

你需要帮助约翰排列出一个合理的奶牛的清理班次,使得每个班次都有奶牛在进行清理,而且动用的奶牛数量可以尽可能的少。

输入格式
第1行:两个空格隔开的整数N和T。

第2..N+1行:第i+1行包含两个整数,分别表示第i头牛可以进行工作的开始时间和结束时间。

输出格式
输出一个整数,表示在每个班次都有奶牛清理的情况下,所需的奶牛最小数量。

如果无法做到每个班次都有奶牛清理,则输出-1。

数据范围
1≤N≤25000,
1≤T≤106
输入样例:
3 10
1 7
3 6
6 10
输出样例:
2

思路

线性dp,f[i]表示完成从0到i的覆盖所需要的最短线段数,那么我们根据最后一段l到r的线段去进行一个转移,那么答案就等于l-1到r-1的这一段内f的最小值加上1,那么涉及到区间最值和单点修改,我们选择线段树优化,那么我们就把这个整个过程放到线段树里面去,维护一个最小值就好了。

代码实现

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005 
#define fi first 
#define se second
#define pb push_back
typedef long long ll;
typedef pair<int ,int> PII;
ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }

const int maxn=25010,M=1e6+10;
int n,m;

struct range {
    int l,r;
    bool operator < (const range &a) const {
        return r<a.r;
    }
}ranges[maxn];

struct node {
    int l,r,w;
}tree[M*4];

void build (int k,int l,int r) {
   tree[k]={l,r,inf};
   if (l==r) return ;
   int mid= (l+r)>>1;
   build (k*2,l,mid),build (k*2+1,mid+1,r);
}

void change_point (int k,int sit,int num) {
      if (tree[k].l==tree[k].r) {
          tree[k].w=min (tree[k].w,num);
          return ;
      }
      int mid=(tree[k].l+tree[k].r)>>1;
      if (sit<=mid) change_point (k*2,sit,num);
      else change_point (k*2+1,sit,num);
      tree[k].w=min (tree[k*2].w,tree[k*2+1].w);
}

int query (int k,int l,int r) {
    if (l<=tree[k].l&&tree[k].r<=r) return tree[k].w;
    int mid= (tree[k].l+tree[k].r)>>1;
    int ans=inf;
    if (l<=mid) ans=query (k*2,l,r);
    if (r>mid) ans=min (ans,query (k*2+1,l,r));
    return ans;
}

int main () {
//    freopen ("data.in","r",stdin);
   cin>>n>>m;
   build (1,0,m);
   
   rev (i,0,n) scanf ("%d%d",&ranges[i].l,&ranges[i].r);
   sort (ranges,ranges+n);

   change_point (1,0,0);
   rev (i,0,n) {
       int l=ranges[i].l,r=ranges[i].r;
       int v=query (1,l-1,r-1)+1;
       change_point (1,r,v);
   }
   int ans=query (1,m,m);
   if (ans==inf) ans=-1;
   cout<<ans<<endl;
  
//    fclose (stdin);
   return 0;
}

posted @ 2020-08-11 22:13  Luglucky  阅读(137)  评论(0编辑  收藏  举报