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)>>1
using 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);
}
}