首页 > 其他分享 >F - Random Update Query

F - Random Update Query

时间:2023-12-12 14:55:53浏览次数:28  
标签:10 frac int text Random Update leq Query lambda

F - Random Update Query

Problem Statement

You are given an integer sequence $A = (A_1, A_2, \ldots, A_N)$ of length $N$.

We will perform the following operation on $A$ for $i = 1, 2, \ldots, M$ in this order.

  • First, choose an integer between $L_i$ and $R_i$, inclusive, uniformly at random and denote it as $p$.
  • Then, change the value of $A_p$ to the integer $X_i$.

For the final sequence $A$ after the above procedure, print the expected value, modulo $998244353$, of $A_i$ for each $i = 1, 2, \ldots, N$.

How to print expected values modulo $998244353$

It can be proved that the expected values sought in this problem are always rational. Furthermore, the constraints of this problem guarantee that if each of those expected values is expressed as an irreducible fraction $\frac{y}{x}$, then $x$ is not divisible by $998244353$.

Now, there is a unique integer $z$ between $0$ and $998244352$, inclusive, such that $xz \equiv y \pmod{998244353}$. Report this $z$.

Constraints

  • All input values are integers.
  • $1 \leq N, M \leq 2 \times 10^5$
  • $0 \leq A_i \leq 10^9$
  • $1 \leq L_i \leq R_i \leq N$
  • $0 \leq X_i \leq 10^9$

Input

The input is given from Standard Input in the following format:

$N$ $M$
$A_1$ $A_2$ $\ldots$ $A_N$
$L_1$ $R_1$ $X_1$
$L_2$ $R_2$ $X_2$
$\vdots$
$L_M$ $R_M$ $X_M$

Output

Print the expected values $E_i$ of the final $A_i$ for $i = 1, 2, \ldots, N$ in the format below, separated by spaces.

$E_1$ $E_2$ $\ldots$ $E_N$

Sample Input 1

5 2
3 1 4 1 5
1 2 2
2 4 0

Sample Output 1

499122179 1 665496238 665496236 5

We start from the initial state $A = (3, 1, 4, 1, 5)$ and perform the following two operations.

  • The first operation chooses $A_1$ or $A_2$ uniformly at random, and changes its value to $2$.
  • Then, the second operation chooses one of $A_2, A_3, A_4$ uniformly at random, and changes its value to $0$.

As a result, the expected values of the elements in the final $A$ are $(E_1, E_2, E_3, E_4, E_5) = (\frac{5}{2}, 1, \frac{8}{3}, \frac{2}{3}, 5)$.


Sample Input 2

2 4
1 2
1 1 3
2 2 4
1 1 5
2 2 6

Sample Output 2

5 6

Sample Input 3

20 20
998769066 273215338 827984962 78974225 994243956 791478211 891861897 680427073 993663022 219733184 570206440 43712322 66791680 164318676 209536492 137458233 289158777 461179891 612373851 330908158
12 18 769877494
9 13 689822685
6 13 180913148
2 16 525285434
2 14 98115570
14 17 622616620
8 12 476462455
13 17 872412050
14 15 564176146
7 13 143650548
2 5 180435257
4 10 82903366
1 2 643996562
8 10 262860196
10 14 624081934
11 13 581257775
9 19 381806138
3 12 427930466
6 19 18249485
14 19 682428942

Sample Output 3

821382814 987210378 819486592 142238362 447960587 678128197 687469071 405316549 318941070 457450677 426617745 712263899 939619994 228431878 307695685 196179692 241456697 12668393 685902422 330908158

 

解题思路

  令 $E_i$ 表示第 $i$ 个数的期望值,在没有执行任何操作前显然都有 $E_i = a_i$。对于某个询问 $(l,r,x)$ 如果 $i \in [l,r]$,记 $\lambda = r-l+1$,那么第 $i$ 个数有 $\frac{1}{\lambda}$ 的概率变成 $x$,有 $\frac{\lambda - 1}{\lambda}$ 的概率还是其本身即 $E_i$,因此第 $i$ 个数的期望就变成了 $E_i \gets \frac{1}{\lambda} \cdot x + \frac{\lambda - 1}{\lambda} \cdot E_i$。

  显然对于每个询问我们不可能一个个数去修改,这样做的时间复杂度为 $O(nm)$。可以发现在每个询问中我们都需要对区间 $[l,r]$ 中的每个 $E_i$ 先乘上一个数 $\frac{\lambda - 1}{\lambda}$,再加上一个数 $\frac{x}{\lambda}$,因此容易想到用线段树去维护。

  线段树的节点维护两个懒标记,$\text{sum}$ 表示这个区间累加的值,$\text{prod}$ 表示这个区间累乘的值。在一次操作中假设要对某个区间的数先乘上 $p$ 再加上 $s$,考虑懒标记如何更新。不妨假设当前的懒标记最后作用在 $E_i$ 上,那么 $E_i$ 就会被更新成 $E_i \times \text{prod} + \text{sum}$,再更新就会得到 $E_i \times (\text{prod} \cdot p) + (\text{sum} \cdot p + s)$,即对应的懒标记的更新就是 $\displaylines{\begin{cases} \text{sum} = \text{sum} \cdot p+ s \\ \text{prod} = \text{prod}\cdot p \end{cases}}$。

  在执行完所有的操作后只需单点查询,那么第 $i$ 个数的期望就是 $a_i \times \text{prod} + \text{sum}$。可以发现线段树只有下传懒标记的操作,而没有向上更新的操作。

  另外这题还有对应的扩展,参考题目 [AHOI2009] 维护序列,需要查询区间和,每次的修改操作是对某个区间加上或乘上某个数。

  AC 代码如下,时间复杂度为 $O(m \log{n})$:

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 10, mod = 998244353;

int a[N];
struct Node {
    int l, r, s, p;
}tr[N * 4];

void build(int u, int l, int r) {
    tr[u] = {l, r, 0, 1};
    if (l == r) {
        tr[u].p = a[l] % mod;
    }
    else {
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
    }
}

void pushdown(int u) {
    if (tr[u].s || tr[u].p != 1) {
        tr[u << 1].s = (1ll * tr[u << 1].s * tr[u].p + tr[u].s) % mod;
        tr[u << 1].p = 1ll * tr[u << 1].p * tr[u].p % mod;
        tr[u << 1 | 1].s = (1ll * tr[u << 1 | 1].s * tr[u].p + tr[u].s) % mod;
        tr[u << 1 | 1].p = 1ll * tr[u << 1 | 1].p * tr[u].p % mod;
        tr[u].s = 0;
        tr[u].p = 1;
    }
}

void modify(int u, int l, int r, int s, int p) {
    if (tr[u].l >= l && tr[u].r <= r) {
        tr[u].s = (1ll * tr[u].s * p + s) % mod;
        tr[u].p = 1ll * tr[u].p * p % mod;
    }
    else {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, s, p);
        if (r >= mid + 1) modify(u << 1 | 1, l, r, s, p);
    }
}

int query(int u, int x) {
    if (tr[u].l == tr[u].r) return (tr[u].s + tr[u].p) % mod;
    pushdown(u);
    if (x <= tr[u].l + tr[u].r >> 1) return query(u << 1, x);
    return query(u << 1 | 1, x);
}

int qmi(int a, int k) {
    int ret = 1;
    while (k) {
        if (k & 1) ret = 1ll * ret * a % mod;
        a = 1ll * a * a % mod;
        k >>= 1;
    }
    return ret;
}

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", a + i);
    }
    build(1, 1, n);
    while (m--) {
        int l, r, x;
        scanf("%d %d %d", &l, &r, &x);
        int t = r - l + 1, p = qmi(t, mod - 2);
        modify(1, l, r, 1ll * x * p % mod, (t - 1ll) * p % mod);
    }
    for (int i = 1; i <= n; i++) {
        printf("%d ", query(1, i));
    }
    
    return 0;
}

 

参考资料

  Editorial - AtCoder Beginner Contest 332:https://atcoder.jp/contests/abc332/editorial/7926

标签:10,frac,int,text,Random,Update,leq,Query,lambda
From: https://www.cnblogs.com/onlyblues/p/17896596.html

相关文章

  • ElasticSearch之Node query cache settings
    对于filter查询,ElasticSearch提供了缓存查询结果的特性,当缓存中存在满足查询条件要求的数据时,直接从缓存中提取查询结果。对于ElasticSearch节点,该节点上的所有shard共享同一个缓存区域。ElasticSearch基于LRU算法来管理缓存中的数据,当空间不足以承载最新的查询操作的结果时,使用......
  • power query索引列、重复列、拆分和提取
    powerquery索引列、重复列、拆分和提取一、索引列1、进入PQ编辑器2、添加索引列添加列——索引列——可自定义索引列 二、重复列功能:数据清洗时想保证数据的完整性,但又需要对某些列进行拆分、提取等操作时,一般先重复想处理的列1、添加列——选中要重复的列——点击‘......
  • power query自定义列和条件列
    Excel从基础到M函数PowerQuery超级整理建议使用office365进入PQ:选中表格任意位置——开始——数据——自表格区域——勾选表包含标题——确定——进入PQ编辑器 要使用PQ编辑器,表格只能支持两种格式:1、公式里设置表格名称(选中表格任意位置——数据——自表格/区域——‘创......
  • linux mysql libmysqlcppconn select,update mysql
    #include<chrono>#include<cstring>#include<ctime>#include<fstream>#include<iomanip>#include<iomanip>#include<iostream>#include<memory>#include<mutex>#include<queue>#include<......
  • Random伪随机数,生成的数大部分相同
    Random是主要产生伪随机数的类,它主要包括两个构造函数(无参构造函数和带一个Int32类型参数的构造函数),无参构造函数主要采用系统时间作为随机种子,带参数的构造函数需要自己去指定随机种子。而在很短的时间内生成大量随机数的时候,由于时间相当短暂,很大的可能性一部分随机数生成时,取到......
  • random
    1、浮点数random.random()的返回值是在[0,1)(左闭右开区间)内的随机浮点数。这意味着它可以取到0,但不包括1。所以,random.random()可以返回0,但不能返回1。importrandomprint(random.random())#[0,1)print(random.random())print(random.random())print(rando......
  • react-query使用
    usequery const{isPending,isLoading,error,data}=useQuery({//返回当前请求的状态,错误信息,以及返回的数据queryKey:['repoData'],//【必填】,自定义查询的键,类型为数组,也可以存放变量,[repoData,id],当id发生变化时,会自动请求接口queryFn:()=>//......
  • sqlalchemy 实现 mysql INSERT INTO...ON DUPLICATE KEY UPDATE语法
    1.前言myql的INSERTINTO...ONDUPLICATEKEYUPDATE语句,简单点来说,就是如果记录不存在,则插入,如果记录存在,则更新。那怎么判断记录存在否?——主键、唯一键。那不是可以使用replace语句吗?——原理上可以,但是sqlalchemyorm中的的实现,是使用merge语法,这个语法有一个限制,就是判......
  • 【题解】AtCoder abc322_f Random Update Query
    传送门:https://atcoder.jp/contests/abc332/tasks/abc332_f容易发现,对于一个位置$i$,$A_i$的最终值是由对$i$的最后一次赋值操作决定的;因此,将所有操作按时间顺序倒过来考虑,则由第$j$次操作决定$A_i$最终值的概率为"在第$(j+1)$~$m$次操作中没有修改过$i$的概率"与"第......
  • 转换考勤系统中的数据(II)(Power Query)
    let源=Excel.CurrentWorkbook(){[Name="表1"]}[Content],添加姓名列=Table.AddColumn(源,"姓名",eachif[列10]="姓名:"then[列5]&[列11]elsenull),姓名列填充=Table.FillDown(添加姓名列,{"姓名"}),筛选掉不需要的行=Table.......