typedeflonglong LL; constint N = 200010; int n, st[N][19], lg2[N];
intgcd(int a, int b){ if (!b) return a; returngcd(b, a % b); }
intquery(int l, int r){ if (r == n+1) return1; int k = lg2[r-l+1]; returngcd(st[l][k], st[r-(1<<k)+1][k]); }
intmain(){ scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &st[i][0]); for (int i = 2; i <= n; i++) lg2[i] = lg2[i>>1] + 1;
for (int k = 1; k <= 18; k++) for (int i = 1; i + (1 << k) - 1 <= n; i++) st[i][k] = gcd(st[i][k-1], st[i+(1<<(k-1))][k-1]); LL res = 0; for (int x = 1; x <= n; x++) { int l = x, r = n+1; while (l < r) { int mid = (l+r) >> 1; if (query(x, mid) == 1) r = mid; else l = mid + 1; } res += n-r+1; }
constint N = 50010; int f[N][16], g[N][16]; int a[N], n, q;
voidinit(){ for (int j = 0; j < 16; j++) { for (int i = 1; i+(1<<j)-1 <= n; i++) { if (!j) f[i][j] = g[i][j] = a[i]; else f[i][j] = max(f[i][j-1], f[i+(1<<(j-1))][j-1]), g[i][j] = min(g[i][j-1], g[i+(1<<(j-1))][j-1]); } } }
intquery(int l, int r){ int k = log2(r-l+1); returnmax(f[l][k], f[r-(1<<k)+1][k]) - min(g[l][k], g[r-(1<<k)+1][k]); }
intmain(){ scanf("%d%d", &n, &q); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); memset(g, 0x3f, sizeof g); init();
for (int i = 1, l, r; i <= q; i++) { scanf("%d%d", &l, &r); printf("%d\n", query(l, r)); }
return0; }
[SCOI2007] 降水量
我们常常会说这样的话:“X 年是自 Y 年以来降雨量最多的”。它的含义是 X 年的降雨量不超过 Y 年,且对于任意 Y<Z<X,Z 年的降雨量严格小于 X 年。例如 2002、2003、2004 和 2005 年的降雨量分别为 4920、5901、2832 和 3890,则可以说“2005 年是自 2003 年以来最多的”,但不能说“2005 年是自 2002 年以来最多的”由于有些年份的降雨量未知,有的说法是可能正确也可以不正确的。
输入格式
输入仅一行包含一个正整数 n,为已知的数据。以下 n 行每行两个整数 yi 和 ri,为年份和降雨量,按照年份从小到大排列,即 yi<yi+1。下一行包含一个正整数 m,为询问的次数。以下 m 行每行包含两个数 Y 和 X,即询问“X 年是自 Y 年以来降雨量最多的。”这句话是“必真”、“必假”还是“有可能”。
#define fi first #define se second typedef pair<int, int> PII; constint N = 70010, M = 10010, INF = 0x3f3f3f3f; int n, m, h[N], f[N][16]; vector<int> nums; PII dat[N], qry[M]; int L[N], R[N], k;
voidinit(){ for (int j = 1; j < 16; j++) for (int i = 1; i+(1<<j)-1 <= nums.size(); i++) f[i][j] = max(f[i][j-1], f[i+(1<<(j-1))][j-1]); }
intquery(int f[][16], int l, int r){ int k = log2(r-l+1); returnmax(f[l][k], f[r-(1<<k)+1][k]); }
intgetrange(int x){ int p = upper_bound(L, L+k, x) - L - 1; if (p < 0 || p >= k) return INF; if (L[p] <= x && x <= R[p]) return p; return INF; }
voidsolve(int y, int x){ int b = nums[y-1], a = nums[x-1]; if (f[x][0] > h[y]) returnputs("false"), void();
if (y+1 == x) { // 判断是否处在同一区间中 if (getrange(b) == getrange(a) && h[x] < INF) returnputs("true"), void(); returnputs("maybe"), void(); } int z = query(f, y+1, x-1); if (z >= h[x] || z >= h[y]) returnputs("false"), void();
if (h[x] == INF || h[y] == INF) returnputs("maybe"), void(); // 判断是否处在同一区间中 if (getrange(b) != getrange(a)) returnputs("maybe"), void();
returnputs("true"), void(); }
intmain(){ memset(h, 0x3f, sizeof h); scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d%d", &dat[i].fi, &dat[i].se), nums.push_back(dat[i].fi);
for (int i = 1; i <= n; i++) { int j = i+1; while (j <= n && dat[j].fi == dat[i].fi + j - i) j++; L[k] = dat[i].fi, R[k] = dat[j-1].fi; i = j-1; k++; }
scanf("%d", &m); for (int i = 1; i <= m; i++) scanf("%d%d", &qry[i].fi, &qry[i].se), nums.push_back(qry[i].fi), nums.push_back(qry[i].se); sort(nums.begin(), nums.end()); nums.erase(unique(nums.begin(), nums.end()), nums.end());
for (int i = 1; i <= n; i++) { int idx = find(dat[i].fi); f[idx][0] = h[idx] = dat[i].se; } init(); for (int i = 1; i <= m; i++) { int y = find(qry[i].fi), x = find(qry[i].se); solve(y, x); } return0; }
[CF1878E] Iva & Pav
给定长度为 n 的数组 a,定义 f(l,r) 是 [l,r] 的区间按位和,给定 q 个查询,每个查询包含 k,l 要求找到最大的 r 使得 f(l,r)≥k,如果不存在输出 −1。