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
∑i∈SAi/∑i∈SBi 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
∑i∈SAi/∑i∈SBi 最小值
思路: 经典01分数规划做法,加上用树状数组维护最小值
#include<bits/stdc++.h>
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);
}