Processing math: 100%
  1. 1 Refrain Anan Ryoko
  2. 2 镇命歌 -しずめうた- 瀧沢一留
  3. 3 Pure SCHAT10(影)
  4. 4 Lemon Soda NGC 3.14/Tenkitsune
  5. 5 summer vibe Cyan Lpegd
  6. 6 DJ Okawari - Flower Dance(钢琴原版) Oturans
  7. 7 花降らし n-buna/初音ミク
  8. 8 Lemon 米津玄師
  9. 9 明けない夜、醒めない夢 Yunomi
  10. 10 ニゲラの花束 鎖那
  11. 11 ひだまりの郷 八乙女葦菜
  12. 12 Pneumatic Tokyo EnV
  13. 13 摘星座的女孩 Rainbowets
Refrain - Anan Ryoko
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

noi.ac 782 【CSP2019模拟 Day 2】a 题解

题意简述

一个长度为n<=1e5的序列,支持两种操作:

  1. 等概率随机打乱区间[l,r]
  2. 求区间[l,r]和的期望值

所有结果(珂能是分数形式)都对998244353取膜。

思路

打乱区间[l,r]相当于把l,r中的数都变成a[lr]的平均值。线段树,区间覆盖区间求和,即珂。

具体思路

为什么这个思路是对的?

随机打乱区间l,r,对于[l,r]中的某一个数x,因为是等概率随机打乱,所以它出现在每一个位置的概率都是相等的,都是1rl+1。所以,[l,r]被打乱之后,每个位置的期望都是相等的,它都等于a[lr]的平均值。

那至少区间不重叠的时候,这个算法就正确了。

那么如果我们的区间有重叠怎么办呢?重叠了还正确么?

我们先明确一下期望的概念:E(x)表示x的期望值,其中x是随机变量,而E(x)是一个确定的数,表示x的期望。

而我们知道,E(C)=C,也就是“常数的期望等于本身”。所以E(E(x))=E(x),换句话说,期望套几层都是不变的。

所以我们在期望的基础上求期望,求“期望的期望”,求出来的还是“期望”,不是别的。

所以答案就是正确的了。膜数有点大,记得开longlong

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define N 155555
#define mod 998244353
#define int long long
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)
#define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
#define p_b push_back
#define sz(a) ((int)a.size())
#define iter(a,p) (a.begin()+p)
void R1(int &x)
{
x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=(f==1)?x:-x;
}
void Rd(int cnt,...)
{
va_list args;
va_start(args,cnt);
F(i,1,cnt)
{
int* x=va_arg(args,int*);R1(*x);
}
va_end(args);
}
class SegmentTree
//线段树
//Build(l,r): 建树,区间为l,r
//Change(l,r,x): 覆盖x在[l,r]上
//Query(l,r): 询问[l,r]的和
//好了,请跳到第106行
{
public:
struct node
{
int l,r,s,a;
}tree[N<<2];
#define ls index<<1
#define rs index<<1|1

#define L tree[index].l
#define R tree[index].r
#define S tree[index].s
#define A tree[index].a

#define lL tree[ls].l
#define lR tree[ls].r
#define lS tree[ls].s
#define lA tree[ls].a

#define rL tree[rs].l
#define rR tree[rs].r
#define rS tree[rs].s
#define rA tree[rs].a
void Update(int index=1)
{
S=lS+rS;
}
void Build(int l,int r,int index=1)
{
L=l,R=r;A=-1;
if (l==r) {R1(S);return;}
int mid=(l+r)>>1;
Build(l,mid,ls); Build(mid+1,r,rs);
Update(index);
}
void ChangeOne(int x,int index=1)
{
x%=mod;
A=x;
S=(x*(R-L+1))%mod;
}
void PushDown(int index=1)
{
if (A!=-1)
{
ChangeOne(A,ls);
ChangeOne(A,rs);
A=-1;
}
}
void Change(int l,int r,int x,int index=1)
{
if (l>R or L>r) return;
if (l<=L and R<=r) return ChangeOne(x,index);
PushDown(index);
Change(l,r,x,ls); Change(l,r,x,rs);
Update(index);
}
int Query(int l,int r,int index=1)
{
if (l>R or L>r) return 0;
if (l<=L and R<=r) return S;
PushDown(index);
return (Query(l,r,ls)+Query(l,r,rs))%mod;
}
}T;
int n,m;
void Input()
{
Rd(2,&n,&m);
T.Build(1,n);
}

int qpow(int a,int b)
{
int r=1;
while(b)
{
if (b&1) r=r*a%mod;
a=a*a%mod,b>>=1;
}
return r;
}
int mod_div(int a,int b){return a*qpow(b,mod-2)%mod;}
void Soviet()
{
F(i,1,m)
{
int o,l,r;Rd(3,&o,&l,&r);
if (o==1)
{
int s=T.Query(l,r)%mod,c=(r-l+1);
T.Change(l,r,mod_div(s,c));
}
if (o==2)
{
printf("%lld\n",T.Query(l,r)%mod);
}
}
}

#define Flan void
Flan IsMyWife()
{
Input();
Soviet();
}
#undef int //long long
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}
w