POJ3171 Cleaning Shifts 数据结构

来源:互联网 发布:数值计算方法与算法 编辑:程序博客网 时间:2024/06/03 23:43


http://poj.org/problem?id=3171

这是一道数据结构题,题目大意为 :

   FJ要打扫区间[M..E],有N 头奶牛,他们打扫区间 [T1,T2]的费用S。问最少要花费多少钱才能打扫完区间[M..E],如果 无法打扫完,就输出-1。


    这是一道比较简单的数据结构题,但稍微用到了dp的思想。

    首先按照打扫区间按第一关键字维M,第二关键字为E由小到大排序。然后遍历这些打扫区间;首先查询[M-1,E],找到打扫到区间内某点的最小花费min。然后在线段中E的位置插入值min+s,表示修到E这个位置最少花费min+s。查询和插入操作可用线段树来完成。中间注意,是否会出现间断的现象,就是某段区间没有牛打扫。


#include<stdio.h>#include<string.h>#include<algorithm>#define dmid int mid=(p.left+p.right)>>1using namespace std;int n,m,e,tot;struct node{int left,right;int lc,rc;int m;}tree[180000];struct Cow{int left,right,s;    bool operator<(const Cow &a) const    {    return left<a.left||left==a.left&&right<a.right;    }}cow[100010];void build(int root,int l,int r){node &p=tree[root];p.left=l;p.right=r;p.m=-1;if(l==r) return;dmid;build(p.lc=++tot,l,mid);build(p.rc=++tot,mid+1,r);}void insert(int root,int pos,int v){node &p=tree[root];p.m=p.m==-1?v:min(v,p.m);if(p.left==p.right) return;dmid;if(pos<=mid) insert(p.lc,pos,v);    else  insert(p.rc,pos,v);}int deal(int a,int b){if(a==-1&&b==-1) return -1;if(a==-1) return b;if(b==-1) return a;return a<b?a:b;}int query(int root,int l,int r){node &p=tree[root];if(p.left==l&&p.right==r) return p.m;    dmid;    if(mid>=r)     return query(p.lc,l,r);    else if(mid<l)     return query(p.rc,l,r);    else     {    int a=query(p.lc,l,mid);    int b=query(p.rc,mid+1,r);    return deal(a,b);    }}main(){//freopen("in.txt","r",stdin);bool flag;int cur=0,mm;while(scanf("%d%d%d",&n,&m,&e)!=EOF){flag=true;for(int i=1;i<=n;++i) scanf("%d%d%d",&cow[i].left,&cow[i].right,&cow[i].s);sort(cow+1,cow+1+n);tot=0;build(0,m-1,e);insert(0,cur=m-1,0);for(int i=1;i<=n;++i){if(cow[i].left>cur+1){printf("-1\n");flag=false;break;}mm=query(0,cow[i].left-1,cow[i].right);if(mm==-1) continue;insert(0,cow[i].right,mm+cow[i].s);cur=max(cur,cow[i].right);}if(!flag) continue;mm=query(0,e,e);printf("%d\n",mm);}}