有一个非常显然的结论,每次调整是
O
(
1
)
O(1)
O(1)的。道理非常简单,设
a
i
,
j
a_{i,j}
ai,j表示
i
i
i号奖池第
j
j
j张彩票的贡献,当
l
i
l_i
li增加
1
1
1时,显然会拿
i
i
i奖池的彩票去换比它更大的,因为
a
i
,
j
−
1
′
>
a
i
,
j
a'_{i,j-1}>a_{i,j}
ai,j−1′>ai,j,那么既然原来的第
j
j
j张换不过,那么改变过后的
j
−
1
j-1
j−1肯定也换不过,同理
l
i
l_i
li减少
1
1
1时也最多换一张。
那么直接用线段树就做完了。
细心题,难以评价。
为什么调不对呢。。。。
实锤了,我不会写代码。
#include<bits/stdc++.h>#define ll long long#define fi first#define se second#define pb push_back#define inf 0x3f3f3f3f#define db long double#define cpx complex<db>usingnamespace std;
constint N=2e5+5;
int n,m,Q;
ll sz[N],L[N],val[N];
db res;
structnode{
db min,max;
int posmin,posmax;
}t[N<<2];
voidpushup(int p){
t[p].max=max(t[p<<1].max,t[p<<1|1].max);
t[p].posmax=(t[p<<1].max>t[p<<1|1].max)?t[p<<1].posmax:t[p<<1|1].posmax;
t[p].min=min(t[p<<1].min,t[p<<1|1].min);
t[p].posmin=(t[p<<1].min<t[p<<1|1].min)?t[p<<1].posmin:t[p<<1|1].posmin;
}
voidinit(int p,int l){
t[p].max=(sz[l]<L[l])?(1.0*val[l]*L[l]/(sz[l]+L[l])/(sz[l]+L[l]+1)):-inf;
t[p].min=sz[l]?(1.0*val[l]*L[l]/(sz[l]+L[l]-1)/(sz[l]+L[l])):inf;
t[p].posmin=t[p].posmax=l;
}
voidbuild(int p,int l,int r){
if(l==r){
init(p,l);
return;
}
int mid=l+r>>1;
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
pushup(p);
}
db getval(int x){
return1.0*sz[x]/(sz[x]+L[x])*val[x];
}
db calcnow(int x){
return1.0*val[x]*L[x]/(sz[x]+L[x]-1)/(sz[x]+L[x]);
}
db calcnext(int x){
return1.0*val[x]*L[x]/(sz[x]+L[x])/(sz[x]+L[x]+1);
}
voidmodify(int p,int l,int r,int x,int type){
if(l==r){
sz[l]+=type;
init(p,l);
return;
}
int mid=l+r>>1;
x<=mid?modify(p<<1,l,mid,x,type):modify(p<<1|1,mid+1,r,x,type);
pushup(p);
}
voidgetans(){
build(1,1,n);
while(m&&t[1].max>0){
int x=t[1].posmax;
modify(1,1,n,x,1);
m--;
}
for(int i=1;i<=n;i++)res+=getval(i);
}
voidAdd(int x){
res-=getval(x),L[x]++;
modify(1,1,n,x,0);
res+=getval(x);
}
voidMove(int x){
res-=getval(x),L[x]--;
if(sz[x]>L[x]){
modify(1,1,n,x,-1);
m++;
}
elsemodify(1,1,n,x,0);
res+=getval(x);
}
intmain(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m>>Q;
for(int i=1;i<=n;i++)cin>>val[i];
for(int i=1;i<=n;i++)cin>>L[i];
cout.precision(20);
getans();
for(int i=1;i<=Q;i++){
int op,x;
cin>>op>>x;
if(op==1)Add(x);
elseMove(x);
while(m&&t[1].max>0){
int x=t[1].posmax;
res-=getval(x);
modify(1,1,n,x,1);
res+=getval(x),m--;
}
if(sz[x]){
int y=t[1].posmax;
if(y!=x&&t[1].max>calcnow(x)){
res-=getval(x)+getval(y);
modify(1,1,n,x,-1),modify(1,1,n,y,1);
res+=getval(x)+getval(y);
}
}
int y=t[1].posmin;
if(y!=x&&sz[x]<L[x]&&calcnext(x)>t[1].min){
res-=getval(x)+getval(y);
modify(1,1,n,x,1),modify(1,1,n,y,-1);
res+=getval(x)+getval(y);
}
cout<<res<<"\n";
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」