P3924 康娜的线段树
首先考虑每一个
- 区间
的 里包含一个 ;你一定会进入这个区间,贡献 。 - 区间
的 里包含一个 ;你有 概率进入这个区间,贡献 。 - 区间
的 里包含一个 ;你有 概率进入这个区间,贡献 。 - 区间
的 里包含一个 ;你有 概率进入这个区间,贡献 。
总的贡献是
我们从这个计算贡献的过程中清晰地发现,到达某个区间的概率是公比为
对于不带修的情况,可以在建树的过程中记录
下面研究区间加的情况:对于
- 求出初始状态的总期望
; - 每次修改后,遍历
,将 带来的新贡献加入 ; - 输出
。
第二步
对于分母的处理,方便计算起见,我们把所有的
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int N = 1e6 + 10;
int maxDep, dep[N], a[N];
LL pre[N], sum[N << 2];
#define ls p << 1
#define rs p << 1 | 1
inline void refresh(int p) { sum[p] = sum[ls] + sum[rs]; }
void build(int p, int l, int r, int d) {
if (l == r) {
sum[p] = a[l];
dep[l] = d;
maxDep = max(d, maxDep);
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid, d + 1);
build(rs, mid + 1, r, d + 1);
refresh(p);
}
LL ask(int p, int l, int r, int s) {
s += sum[p];
if (l == r) {
return (1LL << (maxDep - dep[l])) * s;
}
int mid = (l + r) >> 1;
return ask(ls, l, mid, s) + ask(rs, mid + 1, r, s);
}
int main() {
// freopen("P3924_1.in", "r", stdin);
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, m, p;
cin >> n >> m >> p;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
build(1, 1, n, 0);
LL ans = ask(1, 1, n, 0);
LL den = 1LL << maxDep;
LL div = __gcd(den, (LL)p);
den /= div, p /= div;
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + (((1 << dep[i] + 1) - 1) << (maxDep - dep[i]));
}
while (m--) {
int l, r, x;
cin >> l >> r >> x;
ans += (pre[r] - pre[l - 1]) * x;
cout << ans * p / den << '\n';
}
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析