题目链接:点此跳转
题目描述:
The 2020 hang gliding world championships are coming to Florida next spring! (You may think it is odd to hold in Florida a sport that requires mountains, but it turns out that hang gliders can be towed to altitude by other aircraft.) The competition is divided into a set of tasks; completing a task successfully gives a pilot a number of points. Either all points are awarded for a task, or none are. For each task, every pilot has a probability of success. A pilot’s score is the total of all successfully completed tasks at the end of the competition.
This year, the organizing committee couldn’t decide on a reasonable number of tasks, so the time slots for tasks overlap. At any given time, there can be multiple tasks going on, but a pilot may only choose one to be competing in at that time. Each pilot may compete in as many tasks as they want given this constraint. The pilots know their own strengths and weaknesses, and will choose tasks in order to maximize their expected score.
You have been offered free hang gliding lessons if you help with scoring software for the event. Among other things, the committee wants the software to be able to predict the winners ahead of time.
Given a set of tasks, each with a time slot and a point score to be awarded for success, and a list of pilots, each with success probabilities for each task, compute the expected score for each pilot, and report the top 3 expected scores.
解题思路:
先把每个项目按照结束时间从小到大排个序,然后开一个线段树记录一下(l,r) l 时间段之前可以获得的最大期望,然后更新r时间节点的最大期望,不断查询更改即可。
Code:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100005;
typedef long long ll;
double indexx[maxn];
int n,m,k;
struct XIANG{
int x,y,id;
double w;
}a[maxn];
struct YONG{
int id;
double x;
}b[maxn];
struct node{
int l,r;
double value;
}tree[maxn<<2];
bool cmp(XIANG a,XIANG b){
return a.y<b.y;
}
bool cmp1(YONG u,YONG v){
return u.x>v.x;
}
void push_up(int x){
tree[x].value=max(tree[x<<1].value,tree[x<<1|1].value);
}
void update(int x,double w){
tree[x].value=max(tree[x].value,w);
}
void bulid(int x,int l,int r){
tree[x].l=l;
tree[x].r=r;
if(l==r){
tree[x].value=0;
return ;
}
int mid=(l+r)>>1;
bulid(x<<1,l,mid);
bulid(x<<1|1,mid+1,r);
push_up(x);
}
void change(int x,int p,double w){ //单点更新
if(tree[x].l==p&&tree[x].r==p){
update(x,w);
return ;
}
int mid=(tree[x].l+tree[x].r)/2;
if(p<=mid) change(x*2,p,w);
else change(x*2+1,p,w);
push_up(x);
}
double query(int l,int r,int x){
if(tree[x].l>=l&&tree[x].r<=r) return tree[x].value;
int mid=(tree[x].l+tree[x].r)/2;
if(r<=mid) return query(l,r,x<<1);
else if(l>mid) return query(l,r,x<<1|1);
else return max(query(l,r,x<<1),query(l,r,x<<1|1));
}
int main()
{
scanf("%d%d",&n,&m);
int cas=0;
for(int i=1;i<=n;i++) {
scanf("%d%d%lf",&a[i].x,&a[i].y,&a[i].w);
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
scanf("%lf",&indexx[j]);
}
bulid(1,0,1e4+7); // 0 ~ 1e4+7 时间段
for(int j=1;j<=n;j++){
double yy=query(0,a[j].x,1); //从0开始查
change(1,a[j].y,yy+a[j].w*indexx[a[j].id]);
}
b[i].x=tree[1].value;
b[i].id=i;
}
sort(b+1,b+1+m,cmp1);
for(int i=1;i<=3;i++){
printf("%d %.2lf\n",b[i].id,b[i].x);
}
return 0;
}