CF1599F Mars 题解

· · 题解

题目大意

每次 check 出一个区间是否能被重排为公差为 d 的等差数列。

乱搞过去的(

首先可以很轻易的算出等差数列的首项。

然后把 d = 0 和 d >0 分开来考虑。

$d>0$ 的话,先 check 一下是否整个区间所有数都不同,这个可以轻易的用线段树实现。 然后在区间内随一些数,若它不是末项的话看它的后继是否在 $[l,r]$ 内即可。可以预处理一个 set 来做。 正确率应该很高,至少我不会卡( 假设每次随 $B$ 个数,那么时间复杂度即为 $O(n\log n + qB\log n)$。 事实上后面这项常数很小,$B$ 取 $100$ 可以通过。 ```cpp /* 60 + 0 + 100 + 64 = 224. */ //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native") #include <bits/stdc++.h> using namespace std; #define int long long inline int read() { int sum = 0, nega = 1; char ch = getchar(); while (ch > '9'||ch < '0') { if (ch == '-') nega = -1; ch = getchar(); } while (ch <= '9' && ch >= '0') sum = sum * 10 + ch - '0', ch = getchar(); return sum * nega; } const int N = 2e5 + 9, mod = 1e9 + 7; inline int Pow(int x, int y) { int res = 1, base = x; while(y) { if(y & 1) res = res * base % mod; base = base * base % mod; y >>= 1; } return res; } int tr[N << 2], nxt[N], n, q, a[N]; inline int lc(int p) {return p << 1;} inline int rc(int p) {return p << 1 | 1;} inline void build(int l, int r, int p) { if(l == r) {tr[p] = nxt[l]; return ;} int mid = (l + r) >> 1; build(l, mid, lc(p)), build(mid + 1, r, rc(p)); tr[p] = min(tr[lc(p)], tr[rc(p)]); return ; } inline int query(int l, int r, int p, int L, int R) { if(L <= l && r <= R) return tr[p]; int res = 1e9, mid = (l + r) >> 1; if(mid >= L) res = min(res, query(l, mid, lc(p), L, R)); if(mid < R) res = min(res, query(mid + 1, r, rc(p), L, R)); return res; } map<int, int> mp; set<int> s[N]; int cnt, tmp[N], sum[N], eq[N]; inline bool find(int t, int l, int r) { if(!mp[t]) return 0; int po = mp[t]; if(s[po].lower_bound(l) == s[po].end()) return 0; if(*s[po].lower_bound(l) > r) return 0; return 1; } signed main() { int B = 100; n = read(), q = read(); for (int i = 1; i <= n; i++) a[i] = read(), sum[i] = (sum[i - 1] + a[i]) % mod, eq[i] = eq[i - 1] + (a[i] == a[i - 1]); for (int i = 1; i <= n; i++) if(!mp[a[i]]) mp[a[i]] = ++cnt; for (int i = 1; i <= n; i++) s[mp[a[i]]].insert(i); for (int i = 1; i <= cnt; i++) tmp[i] = n + 1; for (int i = n; i >= 1; i--) nxt[i] = tmp[mp[a[i]]], tmp[mp[a[i]]] = i; build(1, n, 1); for (int i = 1; i <= q; i++) { int l = read(), r = read(), d = read(), len = (r - l + 1); if(l == r) {puts("Yes"); continue;} if(query(1, n, 1, l, r) <= r && d) {puts("No"); continue;} if(!d) { if(eq[r] - eq[l] == r - l) puts("Yes"); else puts("No"); continue; } int su = (sum[r] - sum[l - 1] + mod) % mod, t = (su - len * (len - 1) / 2 % mod * d % mod + mod) % mod; // cout << su << " " << t << endl; t = t * Pow(len, mod - 2) % mod; int sb = (t + (len - 1) * d) % mod; if(!find(t, l, r)) {puts("No"); continue;} bool fl = 0; for (int j = 1; j <= B; j++) { int x = l + rand() % len; if(a[x] == sb) continue; if(!find((a[x] + d) % mod, l, r)) { puts("No"); fl = 1; break; } } if(!fl) puts("Yes"); } return 0; } ```