给你个n个数的数列,找出所有区间内不能被区间其他数整除的数的个数之和。
#pragma warning(disable:4996)
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#define mod 1000000000+7
#define N 100000+5
using namespace std;
int x[N], y[N], a[N], p[10005];
vector<int>mul[10005];
int n;
int main(){
//填充因子vector
for (int i = 1; i <= 10000; i++){
for (int j = 1; j <= i; j++){
if (i%j == 0)mul[i].push_back(j);
}
}
while (scanf("%d", &n) != EOF){
for (int i = 1; i <= n; i++){
scanf("%d", a + i);
//初始化x,y数组
x[i] = 0;
y[i] = n + 1;
}
//此时p[i]表示i出现的左最靠近当前数字的位置
memset(p, 0, sizeof(p));
for (int i = 1; i <= n; i++){
int tmp = 0;
for (int j = 0; j < mul[a[i]].size(); j++){
tmp = max(tmp, p[mul[a[i]][j]]);
}
//填充x数组
x[i] = tmp;
//更新p数组
p[a[i]] = i;
}
for (int i = 0; i < 10005; i++)p[i] = n + 1;
for (int i = n; i >= 1; i--){
int tmp = n + 1;
for (int j = 0; j < mul[a[i]].size(); j++){
tmp = min(tmp, p[mul[a[i]][j]]);
}
//填充y数组
y[i] = tmp;
//更新p数组
p[a[i]] = i;
}
int ans = 0;
for (int i = 1; i <= n; i++){
ans += ((i - x[i])*(y[i] - i));
ans %= mod;
}
cout << ans << endl;
}
return 0;
}
RMQ问题,ST算法+二分
先用ST算法求出区间最值(最大值和最小值),然后枚举区间左端点,二分右端点
#include <iostream>
#include <algorithm>
#include <cmath>
#define N 100000+50
using namespace std;
int a[N];
int maxx[N][20], minx[N][20];
void rmq(int n){
for (int i = 1; i <= n; i++)maxx[i][0] = minx[i][0] = a[i];
for (int j = 1; j < 20; j++){
for (int i = 1; i <= n; i++){
if (i + (1 << j - 1) <= n){
maxx[i][j] = max(maxx[i][j - 1], maxx[i + (1 << j - 1)][j - 1]);
minx[i][j] = min(minx[i][j - 1], minx[i + (1 << j - 1)][j - 1]);
}
}
}
}
int query(int l, int r){
int base = 0;
while ((1 << (base + 1)) < (r - l + 1)) base++;
int maxn = max(maxx[l][base], maxx[r + 1 - (1 << base)][base]);
int minn = min(minx[l][base], minx[r + 1 - (1 << base)][base]);
return maxn - minn;
}
int main(){
int t;
cin >> t;
while (t--){
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++)cin >> a[i];
rmq(n);
long long ans = 0;
for (int i = 1; i <= n; i++){
int l = i, r = n;
while (l <= r){
int mid = (l + r) / 2;
if (query(i, mid) >= k)
r = mid - 1;
else l = mid + 1;
}
ans += (r - i + 1);
}
cout << ans << endl;
}
return 0;
}