题目链接:Codeforces 301D Yaroslav and Divisors
题意:给你
n
个数和
思路:T到死了,弱B各种优化,最后给神奇的思路跪了。
我们考虑区间
[l,r]
的方案数,记
x=[1,r]
的方案数 -
[1,l]
的方案数,
y=p
在区间
[1,l−1]
且
q
在区间
则
ans[l,r]=x−y
。
TMD,菜鸡根本没想过这样写,一直想着用树状数组不断维护区间端点
[l,r]
。然后就死循环了。。。
维护左端点(按
l
升序
维护右端点(按
AC 代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#define PI acos(-1.0)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define fi first
#define se second
#define ll o<<1
#define rr o<<1|1
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 2*1e5 + 1;
const int pN = 1e6;// <= 10^7
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
void add(LL &x, LL y) { x += y; x %= MOD; }
int C[MAXN];
int n, m;
int lowbit(int x) {
return x & (-x);
}
void add(int x, int d) {
while(x <= n) {
C[x] += d;
x += lowbit(x);
}
}
int Sum(int x) {
int s = 0;
while(x > 0) {
s += C[x];
x -= lowbit(x);
}
return s;
}
struct Node {
int l, r, id;
};
Node num[MAXN], num1[MAXN];
bool cmp(Node a, Node b) {
return a.l != b.l ? a.l < b.l : a.r < b.r;
}
bool cmp1(Node a, Node b) {
return a.r != b.r ? a.r < b.r : a.l < b.l;
}
int ans[MAXN];
int a[MAXN], pos[MAXN];
void Update(int x) {
for(int i = x; i <= n; i += x) {
add(pos[i], 1);
}
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
pos[a[i]] = i;
}
CLR(C, 0);
for(int i = 1; i <= m; i++) {
scanf("%d%d", &num[i].l, &num[i].r);
num[i].id = i;
num1[i].l = num[i].l;
num1[i].r = num[i].r;
num1[i].id = i;
}
sort(num+1, num+m+1, cmp);
sort(num1+1, num1+m+1, cmp1);
for(int i = 1; i <= m; i++) ans[i] = 0;
int j = 1, k = 1;
for(int i = 1; i <= n; i++) {
while(j <= m && num[j].l == i) {
ans[num[j].id] -= Sum(num[j].r) - Sum(num[j].l-1);
j++;
}
Update(a[i]);
while(k <= m && num1[k].r == i) {
ans[num1[k].id] += Sum(num1[k].r) - Sum(num1[k].l-1);
k++;
}
}
for(int i = 1; i <= m; i++) {
printf("%d\n", ans[i]);
}
return 0;
}