P5278题解
维护是否等差:
-
最大减最小是否等于公差乘长度
-
差的公因数是否是公差
-
没有相同的数
维护信息 :
-
$gcd$ (差的最大公因数)
-
$maxi$, $mini$ (最大值,最小值)
-
$lnum$, $rnum$ (最左,右边的数)
-
$maxpre$ (前驱的最大值(下标))
维护前驱:
不妨设要把 $k$ 改为 $x$ , $k$ 原本是 $y$
-
上一个是 $x$ 的数的 $last$ 记为 $k$
-
下一个是 $x$ 的数的 $pre$ 记为 $k$
-
原来上一个是 $y$ 的数与下一个是 $y$ 的数连接,即前面的 $last$ 为后面,后面的 $pre$ 为前面。若哪个不存在,记为 0。
-
若1,2条件若本来不存在,不考虑。
$pre$ 为前驱,$last$ 为后继,再用 $set$ , $map$ 维护
#include <map>
#include <set>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef set<long long>::iterator si;
const int maxn = 4 * 1e5 + 10;
struct node {
long long gcd, maxi, mini, lnum, rnum, max_pre;
} t[maxn << 2];
map <long long, int> mp;
set <long long> s[maxn];
long long n, m, a[maxn], pre[maxn], last[maxn];
int GCD (int x, int y) {
return y == 0 ? x : GCD (y, x % y);
}
node father (node p, node q) {
node f;
f.max_pre = max (p.max_pre, q.max_pre);
f.gcd = GCD (p.gcd, GCD (q.gcd, abs (q.lnum - p.rnum)));
f.maxi = max (p.maxi, q.maxi);
f.mini = min (p.mini, q.mini);
f.lnum = p.lnum; f.rnum = q.rnum;
return f;
}
void build (int l, int r, int p) {
if (l == r) {
t[p].gcd = 0;
t[p].max_pre = pre[l];
t[p].maxi = t[p].mini = t[p].lnum = t[p].rnum = a[l];
return ;
}
int mid = (l + r) >> 1;
build (l, mid, p << 1);
build (mid + 1, r, p << 1 | 1);
t[p] = father (t[p << 1], t[p << 1 | 1]);
}
void update (int p, int l, int r, int x, int v, int k) {
if (r < x || l > x) return ;
if (l == x && r == x) {
t[p].max_pre = k;
t[p].maxi = t[p].mini = t[p].lnum = t[p].rnum = v;
return ;
}
int mid = (l + r) >> 1;
if (x <= mid) update (p << 1, l, mid, x, v, k);
else update (p << 1 | 1, mid + 1, r, x, v, k);
t[p] = father (t[p << 1], t[p << 1 | 1]);
}
node query (int p, int l, int r, int x, int y) {
if (x <= l && r <= y) {
return t[p];
}
int mid = (l + r) >> 1;
if (y <= mid) return query (p << 1, l, mid, x, y);
if (x > mid) return query (p << 1 | 1, mid + 1, r, x, y);
return father (query (p << 1, l, mid, x, y), query (p << 1 | 1, mid + 1, r, x, y));
}
int main() {
int tmp = 0, res = 0;
scanf ("%lld%lld", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf ("%lld", &a[i]);
if (mp.find(a[i]) == mp.end()) mp[a[i]] = ++ tmp, s[tmp].insert(i);
else {
int x = mp[a[i]]; int y = *--s[x].end();
pre[i] = y; last[y] = i;
s[x].insert(i);
}
}
build (1, n, 1);
for (int i = 1; i <= m; ++i) {
int op; cin >> op;
if (op == 1) {
long long x, y; scanf ("%lld%lld", &x, &y);
x ^= res; y ^= res;
last[pre[x]] = last[x];
pre[last[x]] = pre[x];
int z = a[last[x]];
update (1, 1, n, last[x], z, pre[x]);
s[mp[a[x]]].erase(x);
if (mp.find(y) == mp.end()){
mp[y] = ++tmp, s[tmp].insert(i);
pre[x] = last[x] = 0;
} else {
z = mp[y];
si it = s[z].lower_bound(x);
if (it == s[z].begin()){
pre[x] = 0; last[x] = *it;
pre[*it] = x;
update (1, 1, n, *it, a[*it], x);
} else if (it == s[z].end()){
-- it;
pre[x] = *it; last[x] = 0;
last[*it] = x;
} else {
si it1 = -- it; ++ it;
pre[x] = *it1; last[x] = *it;
last[*it1] = x; pre[*it] = x;
update (1, 1, n, *it, a[*it], x);
}
}
a[x] = y;
update (1, 1, n, x, y, pre[x]);
} else {
long long k, l, r;
scanf ("%lld%lld%lld", &l, &r, &k);
l ^= res; r ^= res; k ^= res;if (r < l) swap (l, r);
node cnt = query (1, 1, n, l, r);
if ((cnt.maxi - cnt.mini == k * (r - l)) && (cnt.gcd == k || !cnt.gcd) && (cnt.max_pre < l || !k)) res ++, printf ("Yes\n");
else printf ("No\n");
}
}
return 0;
}