【学习笔记】CF626G Raffles

这篇具有很好参考价值的文章主要介绍了【学习笔记】CF626G Raffles。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这还是道数据结构题。事实上看数据范围就能看出来。

类似莫队,考虑在上一个询问的基础上求出答案。

有一个非常显然的结论,每次调整是 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,j1>ai,j,那么既然原来的第 j j j张换不过,那么改变过后的 j − 1 j-1 j1肯定也换不过,同理 l i l_i li减少 1 1 1时也最多换一张。

那么直接用线段树就做完了。文章来源地址https://www.toymoban.com/news/detail-433963.html

#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>
using namespace std;
const int N=2e5+5;
int n,m,Q;
ll sz[N],L[N],val[N];
db res;
struct node{
    db min,max;
    int posmin,posmax;
}t[N<<2];
void pushup(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;
}
void init(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;
}
void build(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){
    return 1.0*sz[x]/(sz[x]+L[x])*val[x];
}
db calcnow(int x){
    return 1.0*val[x]*L[x]/(sz[x]+L[x]-1)/(sz[x]+L[x]);
}
db calcnext(int x){
    return 1.0*val[x]*L[x]/(sz[x]+L[x])/(sz[x]+L[x]+1);
}
void modify(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);
}
void getans(){
    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);
}
void Add(int x){
    res-=getval(x),L[x]++;
    modify(1,1,n,x,0);
    res+=getval(x);
}
void Move(int x){
    res-=getval(x),L[x]--;
    if(sz[x]>L[x]){
        modify(1,1,n,x,-1);
        m++;
    }
    else modify(1,1,n,x,0);
    res+=getval(x);
}
int main(){
    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);
        else Move(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";
    }
}

到了这里,关于【学习笔记】CF626G Raffles的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【学习笔记】CF573E Bear and Bowling

    感觉贪心的做法比较自然🤔,推荐 这篇博客 非常经典 牛逼 的贪心思路: 考虑每次加入一个数,位置 i i i 的贡献为 V i = k i × a i + b i V_i=k_itimes a_i+b_i V i ​ = k i ​ × a i ​ + b i ​ ,其中 k i k_i k i ​ 表示 i i i 以前被选的位置的个数, b i b_i b i ​ 表示 i i i 以后被选的数的

    2024年02月07日
    浏览(34)
  • 【学习笔记】CF1783G Weighed Tree Radius

    如果 w v ( u ) w_v(u) w v ​ ( u ) 指代的就是直径,或者说我们再添一项 a v a_v a v ​ ,那么我们几乎就做完了。 于是自然而然想到换一个定义: d ( u , v ) = dist ( u , v ) + a u + a v d(u,v)=text{dist}(u,v)+a_u+a_v d ( u , v ) = dist ( u , v ) + a u ​ + a v ​ 。 发现这样转化过后,设直径的两个端点

    2024年02月16日
    浏览(36)
  • 【学习笔记】CF576D Flights for Regular Customers

    不同于传统的最短路,当我们走到一个节点的时候,还要记录此时经过的边数才能完成转移。但是第二维太大了,太抽象了! 看到 m m m 这么小,很难不想到离散化。那么设 f i , j f_{i,j} f i , j ​ 表示当第 i i i 条边出现时,在节点 j j j 是否可行,注意这是 01 01 01 状态。转移非

    2024年02月12日
    浏览(30)
  • 【学习笔记】CF582D Number of Binominal Coefficients

    注意 P P P 事实上不会影响复杂度,因为关于组合数,我们有一个非常经典的结论: ( n + m m ) binom{n+m}{m} ( m n + m ​ ) 包含的 P P P 的幂的次数等于 n n n 和 m m m 在 P P P 进制下做加法的进位次数。这样,我们只需要关心进位的次数,而不必知道每一位具体是多少。 这个结论的证

    2024年02月12日
    浏览(29)
  • 【学习笔记】CF1835D Doctor‘s Brown Hypothesis

    有点难😅 发现 x , y x,y x , y 在一个强连通块内,这样一定有环🤔 发现可以找到强连通块内所有环长度的 gcd ⁡ gcd g cd ,这样从 x x x 到 y y y 的所有路径的长度都模这个数同余,又因为 K K K 非常大,所以我们总可以遍历整个强连通块并走若干个环,因此只需要从 x x x 到 y y

    2024年02月09日
    浏览(32)
  • 数据结构学习笔记(王道)

    PS:本文章部分内容参考自王道考研数据结构笔记 1.1. 数据结构 数据:是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。 数据元素:数据的基本单位,一个数据元素可由若干数据项组成。 数据项:数据的不可分割的最

    2024年02月03日
    浏览(262)
  • 数据结构-学习笔记

     注意:该文章摘抄之百度,仅当做学习笔记供小白使用,若侵权请联系删除! 什么是数据结构? 数据结构是计算机存储、组织数据的方式。 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。 结构包括逻辑结构和物理结构。 数据的逻辑结构包括4种  (1)集

    2024年01月23日
    浏览(54)
  • 《数据结构》学习笔记

    1.算法分析的两个主要任务:正确性(不变性 + 单调性) + 复杂度。 2.复杂度分析的主要方法: 迭代:级数求和; 递归:递归跟踪 + 递推方程 猜测 + 验证 3.级数: (1)算术级数:与末项平方同阶 T ( n ) = 1 + 2 + ⋯ + n = n ( n + 1 ) 2 = O ( n 2 ) T(n) = 1 + 2 + cdots + n = frac{n(n+1)}{2} =

    2024年01月25日
    浏览(49)
  • Redis数据结构学习笔记

    图文主要参考小林Coding的图解redis数据结构 除了它是内存数据库,使得所有的操作都在内存上进⾏之外,还有⼀个重要因素,它实现的数据结构,使 得我们对数据进⾏增删查改操作时,Redis 能⾼效的处理。 :::tips redisDb 结构 ,表示 Redis 数据库的结构,结构体⾥存放了指向了

    2024年02月02日
    浏览(47)
  • 数据结构学习笔记——多维数组、矩阵

    数组是由n(n≥1)个 相同数据类型 的数据元素组成的有限序列,在定义数组时,会为数组分配一个固定大小的内存空间,用来存储元素,数组在被定义后,其维度不可以被改变。 数组在确定其维度和维界后,元素的个数是固定的,所以不能进行插入和删除运算。数组中最常

    2024年02月03日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包