Codeforces 626G - Raffles(贪心+堆)
考虑对于固定的彩票池 \(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;
}

浙公网安备 33010602011771号