POJ3171 Cleaning Shifts 数据结构


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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值