标签:
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 2743 | Accepted: 955 | 
Description
Input
Output
Sample Input
3 0 4 0 2 3 3 4 2 0 0 1
Sample Output
5
Hint
给出n个小区间[l,r],更新这段区间的代价为c,求覆盖一段区间[m,e]的最小值。
线段树+DP
首先应该将小区间排个序,对于每一个区间[l,r],它能够在[l-1,r]区间上覆盖,找到这段区
间的最小代价。最小代价加上这段区间的代价与r点的代价比較。更新包括r点的区间
段就能够了。
区间查询用线段树。
代码:
//94ms
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100000+100;
const int inf=199999999;
struct node
{
    int minc;
} tree[maxn<<2];
struct Cow
{
    int l;
    int r;
    int c;
} cow[maxn];
bool cmp(Cow a,Cow b)
{
    if(a.l==b.l)
        return a.r<b.r;
    return a.l<b.l;
}
void build(int rt,int l,int r)//建树
{
    tree[rt].minc=inf;
    if(l==r)
        return;
    int m=(l+r)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
}
void update(int rt,int k,int v,int l,int r)//更新所有包括k的区间
{
    if(l==r)
    {
        tree[rt].minc=min(tree[rt].minc,v);
        return;
    }
    int m=(l+r)>>1;
    if(k<=m)
        update(rt<<1,k,v,l,m);
    else
        update(rt<<1|1,k,v,m+1,r);
    tree[rt].minc=min(tree[rt<<1].minc,tree[rt<<1|1].minc);
}
int query(int rt,int l,int r,int L,int R)//查找L,R区间内的最小值
{
    if(l>=L&&r<=R)
    return tree[rt].minc;
    int mid=(l+r)>>1;
    int temp = inf;
    if(L<=mid)
        temp=query(rt<<1,l,mid,L,R);
    if(R>mid)
        temp=min(temp,query(rt<<1|1,mid+1,r,L,R));
    return temp;
}
int main()
{
    int n,m,e;
    while(~scanf("%d%d%d",&n,&m,&e))
    {
        for(int i=0; i<n; i++)
            scanf("%d%d%d",&cow[i].l,&cow[i].r,&cow[i].c);
        int sign=1;
        sort(cow,cow+n,cmp);
        build(1,m-1,e);
        int cur=m-1;
        update(1,cur,0,m-1,e);//将m-1点赋为0.
        for(int i=0; i<n; i++)
        {
            if(cow[i].l>cur+1)//不能所有覆盖
            {
                sign=0;
                break;
            }
            int temp=query(1,m-1,e,cow[i].l-1,cow[i].r);
            update(1,cow[i].r,temp+cow[i].c,m-1,e);
            cur=max(cur,cow[i].r);
        }
        if(sign)
            printf("%d\n",query(1,m-1,e,e,e));
        else
            printf("-1\n");
    }
    return 0;
}
poj 3171 Cleaning Shifts(区间的最小覆盖价值)
标签:
原文地址:http://www.cnblogs.com/bhlsheji/p/5335850.html