首页 > 其他分享 >P3924 康娜的线段树

P3924 康娜的线段树

时间:2024-12-25 21:42:08浏览次数:4  
标签:int 线段 mid build P3924 康娜 qwq

P3924 康娜的线段树

题目描述

小林是个程序媛,不可避免地康娜对这种人类的“魔法”产生了浓厚的兴趣,于是小林开始教她OI。

今天康娜学习了一种叫做线段树的神奇魔法,这种魔法可以维护一段区间的信息,是非常厉害的东西。康娜试着写了一棵维护区间和的线段树。由于她不会打标记,因此所有的区间加操作她都是暴力修改的。具体的代码如下:

struct Segment_Tree{
#define lson (o<<1)
#define rson (o<<1|1)
    int sumv[N<<2],minv[N<<2];
    inline void pushup(int o){sumv[o]=sumv[lson]+sumv[rson];}
    inline void build(int o,int l,int r){
        if(l==r){sumv[o]=a[l];return;}
        int mid=(l+r)>>1;
        build(lson,l,mid);build(rson,mid+1,r);
        pushup(o);
    }
    inline void change(int o,int l,int r,int q,int v){
        if(l==r){sumv[o]+=v;return;}
        int mid=(l+r)>>1;
        if(q<=mid)change(lson,l,mid,q,v);
        else change(rson,mid+1,r,q,v);
        pushup(o);
    }
}T; 

在修改时,她会这么写:

for(int i=l;i<=r;i++)T.change(1,1,n,i,addv);

显然,这棵线段树每个节点有一个值,为该节点管辖区间的区间和。

康娜是个爱思考的孩子,于是她突然想到了一个问题:

如果每次在线段树区间加操作做完后,从根节点开始等概率的选择一个子节点进入,直到进入叶子结点为止,将一路经过的节点权值累加,最后能得到的期望值是多少?

康娜每次会给你一个值 \(qwq\) ,保证你求出的概率乘上 \(qwq\) 是一个整数。

这个问题太简单了,以至于聪明的康娜一下子就秒了。

现在她想问问你,您会不会做这个题呢?

提示

对于100%的数据,保证$1 \leq n,m \leq 10^6 $

\(-1000 \leq a_i,x \leq 1000\)

Solution

显然,树的形态不会改变,每个点被访问到的概率也不会改变,我们只需要记录下每个点的权重 \(p\) 可以理解为对 \(pos\) 修改之后对于 \(pos->rt\) 这一条链上的所有的点的影响。 具体来说:

\(p_x = 2^{maxdep+1}-2^{maxdep-dep_x}\)

然后对 \(p\) 求一个前缀和,每次修改 \(l,r,w\) 只需要将 \(ans\) 加上 \((-sum[l-1]+sum[r])*w\) 就好了

#include<bits/stdc++.h>
#define int long long
const int N=1e6+6;
int lg=20;
using namespace std;
int a[N],p[N],sum[N],dep[N];
int up(int x)
{
    int res=1;
    while(res<x){res<<=1;}
    return res;
}
#define ls x<<1
#define rs x<<1|1
void build(int x,int l,int r,int k)
{
    if(l==r){p[l]=(1<<lg+1)-(1<<lg)/(1<<k);return ;}
    int mid=l+r>>1;
    build(ls,l,mid,k+1);build(rs,mid+1,r,k+1);
}
#undef ls
#undef rs
int n,m,ans,qwq;
int gcd(int x,int y)
{
    return y==0 ? x : gcd(y,x%y);
}
void work()
{
    cin>>n>>m>>qwq;
    build(1,1,n,0);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+p[i];
        ans+=p[i]*a[i];
        //cout<<p[i]<<"\n";
    }
    int k=1<<lg;
    int g=gcd(k,qwq);
    k/=g,qwq/=g;
    for(int i=1,l,r,w;i<=m;i++)
    {
        scanf("%lld%lld%lld",&l,&r,&w);
        ans += (sum[r]-sum[l-1])*w;
        printf("%lld\n",(ans*qwq/k));
    }
}
#undef int
int main()
{
    //freopen("P3924_1.in","r",stdin);freopen("P3924.out","w",stdout);
    work();
    return 0;
}

标签:int,线段,mid,build,P3924,康娜,qwq
From: https://www.cnblogs.com/LG017/p/18631465

相关文章

  • 就像STL那样:封装的动态开点线段树(用于线段树合并)
    Preface起因是这个万恶的\(P9067\),一个数据结构题,当时才搞了01字典树的板子,想\(trytry\)合并的题的,然后就搜到了这道。(虽然最后完全和这个没有关系)。然后感觉用线段树合并做就可以了,于是抄了个之前封装的一个板子,但是一点都不好用(sad)。空间方面又是头疼,感觉封装了又好像没有封装......
  • 线段树1模板 (洛谷p3372)
    关键在于创建一个向上返回的函数up,向下查询的同时将父亲sum和add值传给儿子函数down最后用lazy函数更新sum和add的值先通过build函数是sum数组完成初始化,然后用adds已经quiey函数完成求解,详细注释见代码​#include<iostream>#include<cstdio>usingnamespacestd;intm......
  • 经典区间线段树详解:从原理到实践
    线段树(SegmentTree)是一种非常高效的树形数据结构,用于解决区间查询和修改问题。本文将通过分步骤讲解,带领读者熟练掌握线段树的原理与实现,并探索其应用场景。引言:数组区间修改问题在一些经典问题中,比如给定一个数组,频繁地需要进行以下操作:区间查询:查询数组某一子区间内的最大......
  • 计算几何模板1(点,直线,线段以及之间的相互关系)
    带样例测试可以直接拿来用#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;constdoublepi=acos(-1);//圆周率π精确到15位小数3.141592653589793constdoubleeps=1e-8;//控制精度视题目情况具体情况具体取有的要取到1e-91e-10不......
  • 编程实践|用 MoonBit 实现线段树(三)
    引言在上一篇文章当中我们讨论了如何实现一棵支持区间查询、区间加法的Immutable线段树,并且使用了很多MoonBit语言当中的独特语法。而作为“在MoonBit实现线段树”系列文章的最后一节,让我们来探讨一下如何实现一个同时支持区间乘法和区间加法的线段树,并且探索Immut......
  • P4556 [Vani有约会] 雨天的尾巴 /【模板】线段树合并
    [Vani有约会]雨天的尾巴/【模板】线段树合并题目背景深绘里一直很讨厌雨天。灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。无......
  • 洛谷题单指南-线段树-Points
    原题链接:https://www.luogu.com.cn/problem/CF19D题意解读:坐标系支持集中操作:1.添加一个点(x,y),保证不会重复2.删除一个点(x,y)3.查询刚好比一个点(x,y)的x,y都大的点,优先看刚好比x大的位置,如果该位置有多个点,取y最小的一个,找到则输出点的坐标,找不到则输出-1。解题思路:首先,可......
  • zkw线段树学习笔记
    先%一下zkw。stozkworzzkw线段树是一个改良版的线段树。其功能与传统线段树相同,也是用于维护区间信息。但是zkw线段树有很多优点:代码简短;纯天然非递归;常数小(尤其在差分区间更新时)特点:堆式储存,找父亲只需右移一位。建树和线段树一样,父节点左移一位为左儿子,再+1(或者|......
  • 在一个svg里进行大量线段的绘制,请问有没有什么可以提高性能的办法,类似 winform里的Sus
    在前端开发中,尤其是在处理SVG图形和大量线段绘制时,性能优化是非常重要的。虽然不像WinForms中的`SuspendLayout`和`ResumeLayout`那样直接控制布局更新的暂停与恢复,但在Web环境中也有多种方法可以提高SVG渲染性能。以下是几种常见的优化策略:###1.使用批量更新尽量减少DOM操作......
  • Qt/C++地图测距/显示不同线段的距离/拿到测距结果/测距结束信号
    一、前言说明地图测距在地图组件中属于一个比较小众的功能,但是又不得不提供,有时候用户希望直接在地图上选点,测算距离,尤其是在一些军事领域用的比较多,测距功能提炼出来的共性就是,每一段都有距离,最后鼠标右键或者双击结束测距,然后发个信号传过来总的距离。一般地图厂家也都提供了对......