题面传送门

考虑对于固定的彩票池 \(i\),我们假设现在押了 \(x\) 张彩票。利用差分的思想,从 \(x\) 张彩票变为 \(x+1\) 张时,期望的变化量 \(\Delta E=\dfrac{p_i(x+1)}{l_i+x+1}-\dfrac{p_ix}{l_i+x}=\dfrac{p_il_i}{(l_i+x+1)(l_i+x)}\)。容易发现该函数为关于 \(x\) 的减函数,所以考虑直接贪心的做法:建一个堆 \(st\),维护所有彩票池由当前彩票数量变为当前彩票数量 \(+1\),期望的变化量,贪心 \(t\) 轮每次贪心地取出堆中最大的元素就行了。

接下来考虑有修改的情况:首先我们假设对于修改的元素 \(x\),\(x\) 彩票池押的彩票个数不变,也就是说我们重新计算一遍 \(x\) 彩票池押中的彩票价值的期望值。显然这样不一定是最优的,于是我们考虑再建一个堆 \(st_2\) 维护已经押入彩票池的彩票的价值,每次贪心地取出 \(st_2\) 中最小的元素并加入 \(st\) 中最大的元素(类似于反悔贪心),直到不能再操作为止即可。

由于每次操作只有加一和减一,所以最多只会引起一张彩票的变化,故复杂度是正确的。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=1;
while(!isdigit(c)){if(c=='-') neg=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=neg;
}
const int MAXN=2e5;
const double EPS=1e-10;
const double INF=1e18;
const int MAGIC=15;
int n,t,qu,p[MAXN+5],l[MAXN+5],c[MAXN+5];
double dif(int x,int c){
if(!c) return INF;if(c>l[x]) return 0;
return 1.0*p[x]*l[x]/(c+l[x])/(c-1+l[x]);
}
struct node{
double val;int x,y;
node(int _x=0,int _y=0){val=dif(_x,_y);x=_x;y=_y;}
bool operator <(const node &rhs) const{
return (fabs(val-rhs.val)>EPS)?(val<rhs.val):(x<rhs.x);
}
};
double ans=0;
set<node> nw,cur;
void ins(){
node t=*nw.rbegin();int x=t.x;//assert(fabs(t.val-dif(x,c[x]+1))<EPS);
nw.erase(nw.find(node(x,c[x]+1)));cur.erase(cur.find(node(x,c[x])));
ans+=t.val;c[x]++;
nw.insert(node(x,c[x]+1));cur.insert(node(x,c[x]));
}
void del(){
node t=*cur.begin();int x=t.x;//assert(fabs(t.val-dif(x,c[x]))<EPS);
nw.erase(nw.find(node(x,c[x]+1)));cur.erase(cur.find(node(x,c[x])));
ans-=t.val;c[x]--;
nw.insert(node(x,c[x]+1));cur.insert(node(x,c[x]));
}
int main(){
scanf("%d%d%d",&n,&t,&qu);
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
for(int i=1;i<=n;i++) scanf("%d",&l[i]);
for(int i=1;i<=n;i++) nw.insert(node(i,c[i]+1)),cur.insert(node(i,c[i]));
for(int i=1;i<=t;i++) ins();
while(qu--){
int opt,x;scanf("%d%d",&opt,&x);
// assert(cur.find(node(x,c[x]))!=cur.end());
nw.erase(nw.find(node(x,c[x]+1)));cur.erase(cur.find(node(x,c[x])));
ans-=1.0*p[x]*min(c[x],l[x])/(l[x]+min(c[x],l[x]));
l[x]+=((opt==1)?(1):(-1));
nw.insert(node(x,c[x]+1));cur.insert(node(x,c[x]));
ans+=1.0*p[x]*min(c[x],l[x])/(l[x]+min(c[x],l[x]));
for(int i=1;i<=MAGIC;i++) del(),ins();
printf("%.15lf\n",ans);
}
return 0;
}

Codeforces 626G - Raffles(贪心+堆)的更多相关文章

  1. Codeforces 626G Raffles(贪心+线段树)

    G. Raffles time limit per test:5 seconds memory limit per test:256 megabytes input:standard input ou ...

  2. Codeforces 626G Raffles 【贪心】【线段树】

    题意: 给n个奖池,t张彩票,q次操作. 每个奖池的奖金为pi. 每个奖池现有的彩票的数量为ai,保证ai>=1: q次操作,每次有两种,第i个奖池的现有彩票数量加一,或减一. 不允许投票的数量 ...

  3. 【贪心+堆】XMU 1584 小明的烦恼

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1584 题目大意: 给n(n<=100 000)个任务的耗时和截至时间,问最少不能 ...

  4. BZOJ_2151_种树_贪心+堆+链表

    BZOJ_2151_种树_贪心+堆 Description A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树.园林部门得到指令后,初步规划出n个种树的位置,顺时针编 ...

  5. BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表

    BZOJ_2006_[NOI2010]超级钢琴_贪心+堆+ST表 Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的 音乐 ...

  6. BZOJ_1029_ [JSOI2007]建筑抢修_贪心+堆

    BZOJ_1029_ [JSOI2007]建筑抢修_贪心+堆 Description 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是 ...

  7. 【bzoj4425】[Nwerc2015]Assigning Workstations分配工作站 贪心+堆

    题目描述 佩内洛普是新建立的超级计算机的管理员中的一员. 她的工作是分配工作站给到这里来运行他们的计算研究任务的研究人员. 佩内洛普非常懒惰,不喜欢为到达的研究者们解锁机器. 她可以从在她的办公桌远程 ...

  8. 【bzoj1029】[JSOI2007]建筑抢修 贪心+堆

    题目描述 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建 ...

  9. CodeForces - 158B.Taxi (贪心)

    CodeForces - 158B.Taxi (贪心) 题意分析 首先对1234的个数分别统计,4人组的直接加上即可.然后让1和3成对处理,只有2种情况,第一种是1多,就让剩下的1和2组队处理,另外一 ...

随机推荐

  1. 第四代富士X100F操作学习

    前言 本文为自己通过B站的UP主[阿布垃机手册]整理.原视频地址:[阿布垃机手册][布瞎BB]富士 X100F 相机外部按键 拍人像自己的设置 [X100F相机光圈大小支持F2到F16+Auto]光圈 ...

  2. spring security实现简单的url权限拦截

    在一个系统中,权限的拦截是很常见的事情,通常情况下我们都是基于url进行拦截.那么在spring security中应该怎么配置呢. 大致步骤如下: 1.用户登录成功后我们需要拿到用户所拥有的权限,并 ...

  3. (四)、Docker 镜像

    1.Docker镜像是什么? 镜像是一种轻量级.可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码.运行时.库.环境变量和配置文件. 2.Do ...

  4. vue混入mixin的使用,保证你看的明明白白!

    场景描述 有些时候,我们发现有些组件部分功能代码是几乎是一样的. 这个时候,我们就可以将相同的逻辑代码抽离出来 此时我们的主角混入mixin就登场了 下面我们有a-test和b-test两个组件,点击 ...

  5. xUtils3的使用教程

    首先在build.gradle下的dependencies下添加引用. implementation 'org.xutils:xutils:3.3.36' 然后创建一个表实体. package com ...

  6. NavigationView使用简介

    Android支持直接创建带有NavigationView的Activity,这里主要介绍NavigationView的逻辑. NavigationView通常是跟DrawerLayout一起使用.D ...

  7. linux exit 和 _exit的区别

    今天仔细看了一下exit和_exit这两个函数的区别,实际上exit也是调用了_exit退出函数的,只不过在调用_exit之前,exit还进行了一些多余的工作,也正是因为这样,相比起来exit就没有那 ...

  8. 51nod_1006 最长公共子序列,输出路径【DP】

    题意: 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个 ...

  9. filter tools

    // 过滤商品分类 Vue.filter("cateFilter", (data) => {   let tmp = ["一级分类", "二级分 ...

  10. Zabbix webhook 自定义报警媒介

    场景一:使用企业微信机器人报警 图中的token是:在群组中添加机器人,机器人的webhook地址的key var Wechat = { token: null, to: null, message: ...