Server 01分数规划+树状数组 HDU6240

Server
题面: Alice and Bob are working on a new assignment. In this project, they need to access some information on a website and monitor this web site for consistent t days. In others words, in each day, there must be at least one server in work. Luckily, they can rent some servers in the lab. According to the schedule, there are totally N servers being available. The i-th server can be used from the Si-th day to the Ti-th day. However, using the i-th server require Ai dollars. After a long time of persuasion, the administrator of the machine room agree to give Alice and Bob discount. Each server is assigned with a discount number Bi. If the set of servers they want to use is S, they need to pay ∑ i ∈ S A i / ∑ i ∈ S B i ∑_{i∈S}Ai/∑_{i∈S}Bi iSAi/iSBi dollars. As Alice and Bob are preparing the programs on the servers, they want your help to find a way to minimize the cost of servers.
题意:
每条线段都有两个值a,b,求覆盖[1,t]的所有端点的 ∑ i ∈ S A i / ∑ i ∈ S B i ∑_{i∈S}Ai/∑_{i∈S}Bi iSAi/iSBi 最小值
思路: 经典01分数规划做法,加上用树状数组维护最小值

#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e5+5;
int n,t;
double tree[N];
struct node
{
	int a,b,s,t;
}a[N];

bool cmp(node q,node qq)
{
	if(q.s==qq.s)
		return q.t<qq.t;
	return q.s<qq.s;
}

void update(int x,double val)
{
	while(x>0)
	{
		tree[x]=min(tree[x],val);
		x-=(x)&(-x);
	}
}

double query(int x)
{
	if(x==0)
		return 0.0;
	double res=1e9;
	while(x<=t)
	{
		res=min(res,tree[x]);
		x+=(x)&(-x);
	}
	return res;
}

bool check(double x)
{
	double sum=0;
	int mx=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i].b*x-a[i].a>=0)
		{
			sum+=a[i].b*x-a[i].a;
			if(a[i].s-1<=mx)
				mx=max(mx,a[i].t);
		}
	}
	for(int i=1;i<=t;i++)
		tree[i]=1e9;
	if(mx==t)
		return true;
	update(mx,0);
	for(int i=1;i<=n;i++)
	{
		if(a[i].a-a[i].b*x>0)
		{

			double tmp=query(a[i].s-1);
			update(a[i].t,tmp+a[i].a-a[i].b*x);
		}
		else
		{
			double tmp=query(a[i].s-1);
			update(a[i].t,tmp);
		}
	}
	return sum>=query(t);
}

你可能感兴趣的:(01分数规划,树状数组)