思路就是计算这一段区间的方差, 然后求出区间最小值作为首项, 然后求出首项为a, 公差为k, 长度为r-l+1的等差数列的方差, 这个可以直接推公式. 然后判断两个方差是否在误差范围内. 但是这个方法只得了20分, 还是说我写丑了T_T
// -----[今天不努力, 明天变垃圾]-----
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
#define x first
#define y second
const int MAX_N = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;
//
//
#define int ll
int n, m;
int a[MAX_N];
struct SegMentTree {
int l, r;
int sum1, sum2;
int mn;
} tree[MAX_N * 4];
#define lc (x * 2)
#define rc (x * 2 + 1)
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum1(x) tree[x].sum1
#define sum2(x) tree[x].sum2
#define mn(x) tree[x].mn
inline void push_up(int x) {
sum1(x) = sum1(lc) + sum1(rc);
sum2(x) = sum2(lc) + sum2(rc);
mn(x) = min(mn(lc), mn(rc));
}
void build(int x, int l, int r) {
l(x) = l; r(x) = r;
if(l == r) {
sum1(x) = mn(x) = a[l];
sum2(x) = a[l] * a[l];
return;
}
int mid = (l + r) / 2;
build(lc, l, mid);
build(rc, mid + 1, r);
push_up(x);
}
void update(int x, int k, int val) {
if(l(x) == r(x)) {
sum1(x) = mn(x) = val;
sum2(x) = val * val;
return;
}
int mid = (l(x) + r(x)) / 2;
if(k <= mid) update(lc, k, val);
else update(rc, k, val);
push_up(x);
}
int querymin(int x, int l, int r) {
if(l(x) >= l && r(x) <= r) {
return mn(x);
}
int mid = (l(x) + r(x)) / 2;
int ans = INF;
if(l <= mid) ans = min(ans, querymin(lc, l, r));
if(r > mid) ans = min(ans, querymin(rc, l, r));
push_up(x);
return ans;
}
int querysum1(int x, int l, int r) {
if(l(x) >= l && r(x) <= r) {
return sum1(x);
}
int mid = (l(x) + r(x)) / 2;
int ans = 0;
if(l <= mid) ans += querysum1(lc, l, r);
if(r > mid) ans += querysum1(rc, l, r);
push_up(x);
return ans;
}
int querysum2(int x, int l, int r) {
if(l(x) >= l && r(x) <= r) {
return sum2(x);
}
int mid = (l(x) + r(x)) / 2;
int ans = 0;
if(l <= mid) ans += querysum2(lc, l, r);
if(r > mid) ans += querysum2(rc, l, r);
push_up(x);
return ans;
}
void solve() {
cin >> n >> m;
for(int i = 1; i <= n; ++ i) cin >> a[i];
build(1, 1, n);
int sumyes = 0;
while(m -- ) {
int op, x, y, l, r, k;
cin >> op;
if(op == 1) {
cin >> x >> y;
x ^= sumyes;
y ^= sumyes;
update(1, x, y);
} else {
cin >> l >> r >> k;
l ^= sumyes;
r ^= sumyes;
k ^= sumyes;
int a = querymin(1, l, r); // 首项
int sum1 = querysum1(1, l, r); // 区间和
int sum2 = querysum2(1, l, r); // 区间平方和
int len = (r - l + 1);
double ave = sum1 * 1.0 / len;
if(len == 1) {
cout << "Yes" << '\n';
++ sumyes;
continue;
}
double fc1 = sum2 * 1.0 / len - ave * ave;
double Ave = a + (len - 1) * 1.0 / 2 * k;
double fc2 = Ave * Ave + a * a + k * k * (len - 1) * (2 * len - 1) * 1.0 / 6 - 2.0 * a * Ave + a * k * (len - 1) - Ave * k * (len - 1);
if(abs(fc1 - fc2) < eps) {
cout << "Yes" << '\n';
++ sumyes;
} else {
cout << "No" << '\n';
}
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int ZTY = 1;
//cin >> ZTY;
while(ZTY -- ) {
solve();
}
return 0;
}