[Jzoj] 3426. 封印一击

题目描述

N e s c a f e Nescafe Nescafe N N N 种元素组成(编号为 1 − N 1-N 1N ),第 i i i 种元素有一个封印区 [ a i , b i ] [a_i,b_i] [ai,bi] 。当封印力度 E E E 小于 a i a_i ai 时,该元素获得 a i a_i ai 的封印能量;当封印力度 E E E a i a_i ai b i b_i bi 之间时,该元素将获得 E E E 的封印能量;而当封印力度 E E E 大于 b i b_i bi 时,该元素将被破坏从而不能获得任何封印能量。现在圣主 a p p l e p i applepi applepi 想选择恰当的 E E E ,使得封印获得的总能量尽可能
高。为了封印的最后一击尽量完美,就请你写个程序帮他计算一下吧!

题目解析

首先很容易发现,最优的数一定是区间的端点,所以只要离散后排个序,找出最优的解。

l e f t left left 表示所有元素左端点的和, r i g h t right right 表示所在区间的个数

所以对于当前选的数 E E E,可以得出 a n s = l e f t + r i g h t × E ans=left+right\times E ans=left+right×E

然后就是维护 l e f t left left r i g h t right right

首先标记每个区间的左端点为 1 1 1,右端点为 − 1 -1 1

当遇到左端点时, l e f t − left- left当前点的值,即出去一个区间, r i g h t + + right++ right++,即进入一个新的区间,然后计算值

当遇到右端点时,先计算值,然后 r i g h t − − right-- right,即出去一个区间。因为在区间的右端点时,也算在当前区间,所以先计算值

代码

#include<bits/stdc++.h>
#define N 200005
#define ll long long
using namespace std;
ll n,l,r,ans,pos;
struct A
{
	ll x,t;
}a[N];
bool cmp(A a,A b) {return a.x<b.x;}
int main()
{
	scanf("%d",&n);
	for(int i=1,x,y;i<=n;i++)
	{
	  scanf("%d%d",&x,&y);
	  a[i].x=x,a[i].t=1;
	  a[i+n].x=y,a[i+n].t=-1;
	  l+=x;
	}
	sort(a+1,a+1+n+n,cmp);
	for(int i=1;i<=2*n;i++)
	{
	  if(a[i].t==1)
	  {
	  	r++;l-=a[i].x;
	  	if(ans<a[i].x*r+l) ans=a[i].x*r+l,pos=a[i].x;
	  }
	  else
	  {
	  	if(ans<a[i].x*r+l) ans=a[i].x*r+l,pos=a[i].x;
	  	r--;
	  }
	}
	cout<<pos<<" "<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值