codeforces 799C Fountains 线段树

题意:购买喷泉有两种方式,用硬币或砖石,都有对应的价格,和美丽度。给定初始的硬币和砖石数,要求买两个喷泉且美丽度之和最大。如果不能买两个输出-1

思路:三种情况:两种都用C或D,CD各一个。C,D各一个只要选择能够买得最大美丽度的喷泉。两种都用C或D,选择了一个之后,另外一个能够买得范围就确定了。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int maxn = 100010;
int a[maxn],acost[maxn],b[maxn],bcost[maxn];
struct node
{
	int Max;
	int l,r;
}t[maxn*4];
void build(int root,int l,int r)
{
	t[root].l=l;
	t[root].r=r;//
	t[root].Max=-1;
	if(l==r)
		return;
	int mid=(l+r)>>1;
	build(2*root,l,mid);
	build(2*root+1,mid+1,r);
}
void update(int root,int index,int val)
{
	int l=t[root].l,r=t[root].r;
	if(l==r)
	{
		t[root].Max=max(t[root].Max,val);
		return;//
	}
	int mid=(l+r)>>1;
	if(index<=mid)
	update(2*root,index,val);
	else
	update(2*root+1,index,val);
	t[root].Max=max(t[root*2].Max,t[root*2+1].Max);
}
int query(int root,int ql,int qr)
{
	int l=t[root].l;
	int r=t[root].r;

	if(l==ql&&r==qr)
	{
		return t[root].Max;
	}
	int mid=(l+r)>>1;
	if(qr<=mid)
	return query(2*root,ql,qr);
	else if(ql>mid)
	return query(2*root+1,ql,qr);
	else
	return max(query(2*root,ql,mid),query(2*root+1,mid+1,qr));//2*root+1
}
int main()
{
	int N,C,D;
	while(~scanf("%d%d%d",&N,&C,&D))
	{
		int acnt=0,bcnt=0;
		char ch;
		int c,w;
		int Maxc=-1;
		for(int i=0;i<N;i++)
		{
			scanf("%d%d %c",&c,&w,&ch);
			if(ch=='C')
			{
				a[acnt]=c;acost[acnt++]=w;
			}
			else if(ch=='D')
			{
				b[bcnt]=c;bcost[bcnt++]=w;
			}
			Maxc=max(w,Maxc);
		}
		int ans=-1;
		int res1=-1,res2=-1;
		for(int i=0;i<acnt;i++)
		{
			if(C>=acost[i])
			res1=max(res1,a[i]);
		}
		for(int i=0;i<bcnt;i++)
		{
			if(D>=bcost[i])
			res2=max(res2,b[i]);
		}
		if(res1!=-1&&res2!=-1)ans=res1+res2;
		
		Maxc=max(Maxc,max(C,D));
		build(1,1,Maxc+10);
		for(int i=0;i<acnt;i++)
		{
			int res=-1;
			if(C>acost[i])
			res=query(1,1,C-acost[i]);
			update(1,acost[i],a[i]);
			if(res!=-1)
			ans=max(ans,a[i]+res);
		}
		build(1,1,Maxc);
		for(int i=0;i<bcnt;i++)
		{
			int res=-1;
			if(D>bcost[i])
			res=query(1,1,D-bcost[i]);
			update(1,bcost[i],b[i]);
			if(res!=-1)
			ans=max(ans,b[i]+res);
		}
		if(ans!=-1)
		printf("%d\n",ans);
		else
		printf("0\n");
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值