2026-05-28~06-02 hetao1733837 的刷题记录
05-28
我将开始大战数学相关!
LGP12122 蓝桥杯 2024 省 B 第二场 逆序对期望
分析
这是橙?对于第一次交换,是好做的,第二次要分讨。
那么,如果我们第一次交换了 i , j i,j i,j,不妨 i < j i<j i<j,那么,第二次交换 k , l k,l k,l,同样不妨 k , l k,l k,l,则有:
- i < j , k < l , i , j ∩ k , l = ∅ i<j,k<l,i,j\cap k,l=\varnothing i<j,k<l,i,j∩k,l=∅,则答案为 2 51 × ( 2 i − 1 + 2 n − j ) × ( j − i − 1 ) + ( l − k − 1 ) \frac{2}{51}\times(\frac{2}{i-1}+\frac{2}{n-j})\times(j - i - 1)+(l-k-1) 512×(i−12+n−j2)×(j−i−1)+(l−k−1),对吗?
有点阴间了,这个东西直接结论就是: E ( x ) = 4 ( n − 2 ) 3 E(x)=\frac{4(n-2)}{3} E(x)=34(n−2),但是,为什么?布吉岛。不过似乎有一个 O ( n 5 l o g n ) O(n^5logn) O(n5logn) 的暴力,不过我已经几亿年不回归并排序了/ll
正解
cpp
#include <bits/stdc++.h>
using namespace std;
signed main(){
cout << "65.33";
}
LGP9217 「TAOI-1」拼凑的断音
原题链接:「TAOI-1」拼凑的断音
分析
好的,似乎有什么思路了......就是对于那些怎么加都超不过原始序列最大值的,抛弃掉。剩下的,最大值是好做的,因为可以有类似于等比数列的东西。
换个视角的问题,我们把序列最大值加 s s s 钦定,那么, p × ( m x + s ) q \frac{p\times (mx+s)}{q} qp×(mx+s) 呃,还有一坨概率没算......然后,剩下的,钦定最大值加 s s s 不选,即 1 − p q 1-\frac{p}{q} 1−qp,然后再去弄。好阴啊。
瞅一眼题解看看概率是怎么做的,肯定是一种类似我们之前说的等比的东西。
哦,我们选了这个数之后,剩下的会自动啊吧啊吧,然后就可以了......
所以,我们得到一个式子,我们按照之前那个预处理之后降序排序,可得:
∑ i = 1 m ( 1 − p q ) ( i − 1 ) × p q × ( a i + s ) \sum\limits_{i=1}^{m}{(1-\frac{p}{q})^{(i-1)}\times\frac{p}{q}\times(a_i+s)} i=1∑m(1−qp)(i−1)×qp×(ai+s)
好像是这个东西吧......
哦,还有原始最大值,这个,把就是所有都不变的 ( 1 − p q ) n (1-\frac{p}{q})^n (1−qp)n 的概率去乘即可。看看哪种取模比较优雅吧,这么一推,似乎第二种是优雅的。
正解
cpp
#include <bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
const int N = 100005;
int n, p, q, s, a[N];
int qpow(int a, int b){
int res = 1;
while (b){
if (b & 1){
res = res * a % mod;
}
b >>= 1;
a = a * a % mod;
}
return res;
}
int mx;
vector<int> num;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> p >> q >> s;
for (int i = 1; i <= n; i++){
cin >> a[i];
mx = max(mx, a[i]);
}
for (int i = 1; i <= n; i++){
if (a[i] + s > mx){
num.push_back(a[i]);
}
}
sort(num.begin(), num.end(), greater<int>());
int ans = 0;
for (int i = 0; i < (int)num.size(); i++){
int j = i + 1;
ans = (ans + qpow((q - p) * qpow(q, mod - 2) % mod, j - 1) % mod * p % mod * qpow(q, mod - 2) % mod * (num[i] + s) % mod) % mod;
}
ans = (ans + mx * qpow((q - p) * qpow(q, mod - 2) % mod, (int)num.size())) % mod;
cout << 2 << '\n';
cout << ans;
}
LGP11046 蓝桥杯 2024 省 Java B 星际旅行
分析
显然有一个图在里面......哦,看来就是 bfs 了。那么,启动!差点以为是图上随机游走了。
好吧,纯写 bfs 是全 MLE 的,不知道为啥,可能是我太菜了/ll
那么,不妨跑一遍 Dijkstra,对于那些 d i s x i , j ≤ y i dis_{x_i,j}\le y_i disxi,j≤yi 的,加一下,最后出答案统一除以 Q Q Q。
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, m, Q;
vector<int> e[N];
int d[N][N];
bool vis[N];
void dijkstra(int S){
memset(vis, 0, sizeof(vis));
d[S][S] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
q.push({0, S});
while (!q.empty()){
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = true;
for (int v : e[u]){
if (d[S][v] > d[S][u] + 1){
d[S][v] = d[S][u] + 1;
q.push({d[S][v], v});
}
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> Q;
for (int i = 1, a, b; i <= m; i++){
cin >> a >> b;
e[a].push_back(b);
e[b].push_back(a);
}
memset(d, 0x3f, sizeof(d));
for (int i = 1; i <= n; i++){
dijkstra(i);
}
long long ans = 0;
for (int i = 1, x, y; i <= Q; i++){
cin >> x >> y;
for (int j = 1; j <= n; j++){
if (d[x][j] <= y)
ans++;
}
}
cout << fixed << setprecision(2) << (double)ans / Q;
return 0;
}
启动 BO!
05-30
LGP13800 SWERC 2023 Throwing dice
分析
看蒙了,吓哭了/ll
我不会/ll
无法直输骗分/ll
好吧,猜到了,但是不是很会证。
正解
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005;
int n, m, a[N], b[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> m >> n;
int suma = 0, sumb = 0;
for (int i = 1; i <= m; i++){
cin >> a[i];
suma += a[i];
}
for (int i = 1; i <= n; i++){
cin >> b[i];
sumb += b[i];
}
if (suma + m > sumb + n){
cout << "ALICE";
}
else if (suma + m == sumb + n){
cout << "TIED";
}
else{
cout << "BOB";
}
}
05-31
LGP4550 收集邮票
原题链接:收集邮票
分析
我为何看不出怎么算的?看题解。
期望 DP ,❓
我们设 f i f_i fi 表示取到了第 i i i 张,取完剩下的期望次数,则有转移:
f i = i n × f i + n − i n × f i + 1 + 1 f_i=\frac{i}{n}\times f_i+\frac{n-i}{n}\times f_{i+1}+1 fi=ni×fi+nn−i×fi+1+1
设 g i g_i gi 表示取到第 i i i 张,取完剩下的期望价格,则有转移:
g i = i n × ( g i + f i + 1 ) + n − i n × ( g i + 1 + f i + 1 + 1 ) g_i=\frac{i}{n}\times (g_i+f_i+1)+\frac{n-i}{n}\times (g_{i+1}+f_{i+1}+1) gi=ni×(gi+fi+1)+nn−i×(gi+1+fi+1+1)
其中, f n = g n = 0 f_n=g_n=0 fn=gn=0。
不化简影响这么大吗?
行吧,那么化简可得:
f i = f i + 1 + n n − i g i = i n − i × f i + g i + 1 + f i + 1 + n n − i f_i=f_{i+1}+\frac{n}{n-i} \\ g_i=\frac{i}{n-i}\times f_i+g_{i+1}+f_{i+1}+\frac{n}{n-i} fi=fi+1+n−ingi=n−ii×fi+gi+1+fi+1+n−in
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 10005;
int n;
double f[N], g[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = n - 1; i >= 0; i--){
f[i] = f[i + 1] + 1.0 * n / (n - i);
g[i] = 1.0 * i / (n - i) * (f[i] + 1) + g[i + 1] + f[i + 1] + 1;
}
cout << fixed << setprecision(2) << g[0];
return 0;
}
CF148D Bag of mice
原题链接:D. Bag of mice
分析
好的,作为第一道概率 DP 题。
设 d p i , j dp_{i,j} dpi,j 表示袋子里有 i i i 只白鼠, j j j 只黑鼠时,公主获胜的概率。
那么,对于所有 d p i , 0 dp_{i,0} dpi,0,公主必胜。对于所有 d p 0 , j dp_{0,j} dp0,j,龙必胜。即 d p i , 0 = 1 , d p 0 , j = 0 dp_{i,0}=1,dp_{0,j}=0 dpi,0=1,dp0,j=0。
那么有转移:
d p i , j + = { i i + j j i + j × j − 1 i + j − 1 × j − 2 i + j − 2 × d p i , j − 3 ( j ≥ 3 ) j i + j × j − 1 i + j − 1 × i i + j − 2 × d p i − 1 , j − 2 ( i ≥ 1 , j ≥ 2 ) dp_{i,j}+= \begin{cases} \frac{i}{i+j}\\ \frac{j}{i+j}\times\frac{j-1}{i+j-1}\times\frac{j-2}{i+j-2}\times dp_{i, j-3} (j\ge 3)\\ \frac{j}{i+j}\times\frac{j-1}{i+j-1}\times\frac{i}{i+j-2}\times dp_{i-1, j-2} (i\ge 1,j\ge 2) \end{cases} dpi,j+=⎩ ⎨ ⎧i+jii+jj×i+j−1j−1×i+j−2j−2×dpi,j−3(j≥3)i+jj×i+j−1j−1×i+j−2i×dpi−1,j−2(i≥1,j≥2)
分别表示:公主直接抓了一只白鼠;公主,龙分别抓一只黑鼠,跑出来一只黑鼠;公主,龙分别抓一只黑鼠,跑出来一只白鼠的概率。
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int w, b;
double dp[N][N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> w >> b;
for (int i = 1; i <= w; i++){
dp[i][0] = 1;
}
for (int j = 1; j <= b; j++){
dp[0][j] = 0;
}
for (int i = 1; i <= w; i++){
for (int j = 1; j <= b; j++){
dp[i][j] += (0.0 + i) / (0.0 + i + j);
if (j >= 3){
dp[i][j] += (0.0 + j) / (0.0 + i + j) * (0.0 + j - 1) / (0.0 + i + j - 1) * (0.0 + j - 2) / (0.0 + i + j - 2) * dp[i][j - 3];
}
if (i >= 1 && j >= 2){
dp[i][j] += (0.0 + j) / (0.0 + i + j) * (0.0 + j - 1) / (0.0 + i + j - 1) * (0.0 + i) / (0.0 + i + j - 2) * dp[i - 1][j - 2];
}
}
}
cout << fixed << setprecision(9) << dp[w][b];
}
CF768D Jon and Orbs
原题链接:D. Jon and Orbs
分析
愣了几秒,发现自己好像没有看懂题面。
好吧,看了题解,把题面看懂了:
K K K 种物品,求一次取一件把所有种类取遍的概率不小于 p i 2000 \frac{p_i}{2000} 2000pi 的最小天数。 p i p_i pi 有 Q Q Q 次询问。
那么,对于 K − K ≥ p i 2000 K^{-K}\ge \frac{p_i}{2000} K−K≥2000pi,直接输出似乎就可以了。
正常的话,难道设 d p i , j dp_{i,j} dpi,j 表示进行了 i i i 天,抽出 j j j 种的概率?那么,转移应该形如:
d p i + 1 , j = d p i , j × 1 C j 1 d p i + 1 , j + 1 = d p i , j × 1 C n − j 1 dp_{i+1,j}=dp_{i,j}\times\frac{1}{C_{j}^{1}}\\ dp_{i+1,j+1}=dp_{i,j}\times\frac{1}{C_{n-j}^{1}} dpi+1,j=dpi,j×Cj11dpi+1,j+1=dpi,j×Cn−j11
果真如此吗?那么, d p i , 0 = 0 , d p 0 , j = 0 , d p 0 , 0 = 1 , d p i , i = K − i dp_{i,0}=0,dp_{0,j}=0,dp_{0,0}=1,dp_{i,i}=K^{-i} dpi,0=0,dp0,j=0,dp0,0=1,dpi,i=K−i?
那我怎么搞边界?算了,看看题解吧。
哦,转移思路错了,DP,不只是概率DP,都要从之前有的转移,从之前没有的转移,那叫递归,那不是记忆化搜索!
所以,真正的转移形如:
d p i , j + = { d p i − 1 , j × j k d p i − 1 , j − 1 × k − j + 1 k dp_{i,j}+= \begin{cases} dp_{i-1,j}\times\frac{j}{k}\\ dp_{i-1,j-1}\times\frac{k-j+1}{k} \end{cases} dpi,j+={dpi−1,j×kjdpi−1,j−1×kk−j+1
对于天数,一种方法是可以根据复杂度直接开到最大,另一种自己推导(题解提到了约 7500 7500 7500 天),我们直接开到 1 × 10 4 1\times10^4 1×104。
初始化也没有那么麻烦,只需要: d p 0 , 0 = 1 dp_{0,0}=1 dp0,0=1 即可。
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int M = 10005, K = 1005;
int k, q, p[M];
double dp[M][K];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> k >> q;
for (int i = 1; i <= q; i++){
cin >> p[i];
}
dp[0][0] = 1;
for (int i = 1; i <= 10000; i++){
for (int j = 1; j <= k; j++){
dp[i][j] = dp[i - 1][j] * (double)j / k + dp[i - 1][j - 1] * (double)(k - j + 1) / k;
}
}
for (int i = 1; i <= q; i++){
int ans = 1;
for (int j = 1; j <= 10000; j++){
if (dp[j][k] < p[i] / 2000.0){
ans++;
}
}
cout << ans << '\n';
}
return 0;
}
哦,原来第一发把两个维度搞反了吗/jk
06-01
lz 的恩情还不完,居然给我们蜜雪冰城/ll
好吧,我回家给 zjx 转💴
LGP1850 NOIP 2016 提高组 换教室
原题链接:NOIP 2016 提高组 换教室
分析
居然已经 10 年了吗?好吧,我的人生已经可以以 10 年这个单位来计算了。
我到底在伤感什么?
首先,我要跑一个 O ( v 3 ) O(v^3) O(v3) 的全源最短路,非常好啊!
然后,我们设 f i , j , 0 / 1 f_{i,j,0/1} fi,j,0/1 表示对于第 i i i 节课,已经申请了 j j j 次,这节课申请/不申请的概率(怎么有点怪怪的?)。
转移有:
f i , j , 0 = f i − 1 , j , 0 f i , j , 1 = f i − 1 , j − 1 , 0 × 1 k i + f i − 1 , j − 1 , 1 × 1 k i f_{i,j,0}=f_{i-1,j,0}\\ f_{i,j,1}=f_{i-1,j-1,0}\times \frac{1}{k_i}+f_{i-1,j-1,1}\times \frac{1}{k_i} fi,j,0=fi−1,j,0fi,j,1=fi−1,j−1,0×ki1+fi−1,j−1,1×ki1
感觉这个好假啊......
设 g i , j , 0 / 1 g_{i,j,0/1} gi,j,0/1 表示对于第 i i i 节课,已经申请了 j j j 次,这节课申请/不申请的期望(怎么也有点怪怪的?)。
转移有:
g i , j , 0 = g i − 1 , j , 0 × d c i − 1 , c i g i , j , 0 = g i − 1 , j − 1 , 0 × d c i − 1 , d i + g i − 1 , j − 1 , 1 × d c i − 1 , d i g_{i,j,0}=g_{i-1,j,0}\times d_{c_{i-1}, c_i}\\ g_{i,j,0}=g_{i-1,j-1,0}\times d_{c_{i-1}, d_i}+g_{i-1,j-1,1}\times d_{c_{i-1}, d_i} gi,j,0=gi−1,j,0×dci−1,cigi,j,0=gi−1,j−1,0×dci−1,di+gi−1,j−1,1×dci−1,di
答案为 min i = 1 m min { g n , i , 0 / 1 } \min\limits_{i=1}^{m}{\min\{g_{n,i,0/1}\}} i=1minmmin{gn,i,0/1}。
这个转移感觉假完了/ll
不算完全失败吧。首先,那个 Floyd 想到了。然后,那个状态其实也算是比较接近了,不过差点火候。
我们设 d p i , j , 0 / 1 dp_{i,j,0/1} dpi,j,0/1 表示考虑了前 i i i 个教室,换了 j j j 次,第 i i i 个教室申请换/不申请换的最小期望值。
那么,转移显然:
d p i , j , 0 = min ( d p i − 1 , j , 0 + d i s c i − 1 , c i , d p i − 1 , j − 1 , 1 + d i s c i − 1 , c i × ( 1 − k i − 1 ) + d i s d i − 1 , c i × k i − 1 ) d p i , j , 1 = min ( d p i − 1 , j − 1 , 0 + d i s c i − 1 , c i × ( 1 − k i − 1 ) + d i s c i − 1 , d i × k i , d p i − 1 , j − 1 , 1 + d i s d i − 1 , d i × k i × k i − 1 + d i s d i − 1 , c i × k i − 1 × ( 1 − k i ) + d i s d i − 1 , d i × ( 1 − k i − 1 ) × k i + d i s c i − 1 , c i × ( 1 − k i − 1 ) × ( 1 − k i ) ) dp_{i,j,0}=\min(dp_{i-1,j,0}+dis_{c_{i-1},c_i},dp_{i-1,j-1,1}+ dis_{c_{i-1},c_i}\times(1-k_{i-1})+dis_{d_{i-1},c_i}\times k_{i-1})\\ dp_{i,j,1}=\min(dp_{i-1,j-1,0}+dis_{c_{i-1},c_i}\times(1-k_{i-1})+dis_{c_{i-1},d_i}\times k_i,dp_{i-1,j-1,1}+dis_{d_{i-1},d_i}\times k_i\times k_{i-1}+dis_{d_{i-1},c_i}\times k_{i-1}\times(1-k_i)+dis_{d_{i-1},d_i}\times(1-k_{i-1})\times k_i+dis_{c_{i-1},c_{i}}\times(1-k_{i-1})\times(1-k_i)) dpi,j,0=min(dpi−1,j,0+disci−1,ci,dpi−1,j−1,1+disci−1,ci×(1−ki−1)+disdi−1,ci×ki−1)dpi,j,1=min(dpi−1,j−1,0+disci−1,ci×(1−ki−1)+disci−1,di×ki,dpi−1,j−1,1+disdi−1,di×ki×ki−1+disdi−1,ci×ki−1×(1−ki)+disdi−1,di×(1−ki−1)×ki+disci−1,ci×(1−ki−1)×(1−ki))
简直了/tuu
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 2005, V = 305;
const double INF = 1e18;
int n, m, v, cnte;
int c[N], d[N];
double k[N];
double dp[N][N][2];
int dis[V][V];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> v >> cnte;
for (int i = 1; i <= n; i++)
cin >> c[i];
for (int i = 1; i <= n; i++)
cin >> d[i];
for (int i = 1; i <= n; i++)
cin >> k[i];
memset(dis, 0x3f, sizeof(dis));
for (int i = 1; i <= v; i++)
dis[i][i] = 0;
for (int i = 1, a, b, w; i <= cnte; i++){
cin >> a >> b >> w;
dis[a][b] = dis[b][a] = min({dis[a][b], dis[b][a], w});
}
for (int k = 1; k <= v; k++)
for (int i = 1; i <= v; i++)
for (int j = 1; j <= v; j++)
if (dis[i][k] != 0x3f3f3f3f && dis[k][j] != 0x3f3f3f3f)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
for (int i = 0; i <= n; i++)
for (int j = 0; j <= m; j++)
dp[i][j][0] = dp[i][j][1] = INF;
dp[1][0][0] = 0;
if (m >= 1)
dp[1][1][1] = 0;
for (int i = 2; i <= n; i++){
dp[i][0][0] = dp[i - 1][0][0] + dis[c[i - 1]][c[i]];
for (int j = 1; j <= min(i, m); j++){
dp[i][j][0] = min(dp[i - 1][j][0] + dis[c[i - 1]][c[i]],
dp[i - 1][j][1] + dis[c[i - 1]][c[i]] * (1 - k[i - 1]) + dis[d[i - 1]][c[i]] * k[i - 1]);
dp[i][j][1] = min(dp[i - 1][j - 1][0] + dis[c[i - 1]][c[i]] * (1 - k[i]) + dis[c[i - 1]][d[i]] * k[i],
dp[i - 1][j - 1][1] + dis[d[i - 1]][d[i]] * k[i - 1] * k[i] + dis[d[i - 1]][c[i]] * k[i - 1] * (1 - k[i]) + dis[c[i - 1]][d[i]] * (1 - k[i - 1]) * k[i] + dis[c[i - 1]][c[i]] * (1 - k[i - 1]) * (1 - k[i]));
}
}
double ans = INF;
for (int i = 0; i <= m; i++)
ans = min({ans, dp[n][i][0], dp[n][i][1]});
cout << fixed << setprecision(2) << ans;
return 0;
}
AT-arc219-b ARC219B Reverse Permutation
分析
他管这个玩意叫黄?
放了 O ( n l o g n ) O(nlogn) O(nlogn),思考一下......
难道说对于每个位置进行思考?bur,这么狠吗?上来就给我整个这?
对,第一次看题想到了 字典序只考虑第一位和最后一位,好吧,我承认,最后一位我没想全。
哦,题解的意思应该是,就是对于每一个数 i i i,都有 n − i n-i n−i 个数比他大,换了字典序就变小,所以加一下,最后就能构造出来?然后由于这个要是不相同的话,那么后面的字典序应该就乱了,需要跳出来。
正解
cpp
#include <bits/stdc++.h>
#define mod 998244353
using namespace std;
const int N = 500005;
int T;
int n, p[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> T;
for (int cs = 1; cs <= T; cs++){
int ans = 1;
cin >> n;
for (int i = 1; i <= n; i++){
cin >> p[i];
}
for (int i = 1; i <= n; i++){
if (p[i] == i){
ans = (ans + n - i) % mod;
}
else{
ans = (ans - 1 + mod) % mod;
break;
}
}
cout << ans << '\n';
}
}
06-02
LGP2221 HAOI2012 高速公路
原题链接:HAOI2012 高速公路
分析
区间加+区间求和,显然是线段树。剩下的,我来尝试一个式子。哦,需要线段树维护一下 i × a i i\times a_i i×ai,做完了。
要不直接开贺吧......
正解
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005;
int n, m;
char op;
int l, r, v;
int sum1, sum2, sum3;
struct segtree{
struct node{
int sum[10], tag, l, r;
}tr[N << 2];
void pushup(int p){
tr[p].sum[1] = tr[p << 1].sum[1] + tr[p << 1 | 1].sum[1];
tr[p].sum[2] = tr[p << 1].sum[2] + tr[p << 1 | 1].sum[2];
tr[p].sum[3] = tr[p << 1].sum[3] + tr[p << 1 | 1].sum[3];
}
void build(int p, int l, int r){
tr[p].l = l;
tr[p].r = r;
if (l == r){
tr[p].sum[4] = l * l;
tr[p].sum[5] = l;
return ;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
tr[p].sum[4] = tr[p << 1].sum[4] + tr[p << 1 | 1].sum[4];
tr[p].sum[5] = tr[p << 1].sum[5] + tr[p << 1 | 1].sum[5];
}
void calc(int p, int k){
tr[p].sum[1] += (tr[p].r - tr[p].l + 1) * k;
tr[p].sum[2] += tr[p].sum[5] * k;
tr[p].sum[3] += tr[p].sum[4] * k;
tr[p].tag += k;
}
void down(int p){
calc(p << 1, tr[p].tag);
calc(p << 1 | 1, tr[p].tag);
tr[p].tag = 0;
}
void modify(int p, int s, int t, int val){
if (s <= tr[p].l && tr[p].r <= t){
calc(p, val);
return ;
}
if (tr[p].tag)
down(p);
int mid = (tr[p].l + tr[p].r) >> 1;
if (s <= mid)
modify(p << 1, s, t, val);
if (t > mid)
modify(p << 1 | 1, s, t, val);
pushup(p);
}
void query(int p, int s, int t){
if (s <= tr[p].l && tr[p].r <= t){
sum1 += tr[p].sum[1];
sum2 += tr[p].sum[2];
sum3 += tr[p].sum[3];
return ;
}
if (tr[p].tag)
down(p);
int mid = (tr[p].l + tr[p].r) >> 1;
if (s <= mid)
query(p << 1, s, t);
if (t > mid)
query(p << 1 | 1, s, t);
}
}T;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
T.build(1, 1, n);
for (int cs = 1; cs <= m; cs++){
cin >> op;
if (op == 'C'){
cin >> l >> r >> v;
r--;
T.modify(1, l, r, v);
}
else{
cin >> l >> r;
r--;
sum1 = sum2 = sum3 = 0;
T.query(1, l, r);
int tmp1 = (r - l + 1 - r * l) * sum1 + (l + r) * sum2 - sum3;
int tmp2 = (r - l + 2) * (r - l + 1) / 2;
int GCD = __gcd(tmp1, tmp2);
cout << tmp1 / GCD << "/" << tmp2 / GCD << '\n';
}
}
return 0;
}
原来这样就可以吗/xia