luogu P5610 [Ynoi2013] 大学
https://www.luogu.com.cn/problem/P5610
因为一个数最多log次就会除到1,所以这题的难度其实是在快速定位上面
对于每个约数,用平衡树维护显然很方便,但是常数巨大,无法通过
发现可以用vector+并查集实现快速定位和删除
每个位置指向往后(包括自己)第一个没有被删除的位置,如果这个数被删了就指向下一个
然而vector常数还是巨大
考虑用指针实现,一开始先分配好地址
这样多交几发就可以通过了
code:
#include<bits/stdc++.h>
#define N 100050
#define M 500050
#define ll long long
using namespace std;
inline int read() {
register int x = 0;
register char ch = getchar();
for(; ch < '0' || ch > '9'; ) ch = getchar();
for(; ch >= '0' && ch <= '9'; ) x = (x << 3) + (x << 1) + (ch - 48), ch = getchar();
return x;
}
int *fa[M], *d[M], b[M * 105], *now = b, gs[M];
inline void init(int id, int n) {
for(int i = 0; i <= n; i ++) fa[id][i] = i;
}
inline int get(int id, int x) {
if(x == gs[id]) return x;
return fa[id][x] == x? x : fa[id][x] = get(id, fa[id][x]);
}
#define lowbit(x) (x & -x)
ll t[N];
int n, m, a[N];
inline void update(int x, int y) {
for(; x <= n; x += lowbit(x)) t[x] += y;
}
inline ll query(int x) {
ll ret = 0;
for(; x; x -= lowbit(x)) ret += t[x];
return ret;
}
int main() {
n = read(), m = read();
int mx = 0;
for(int i = 1; i <= n; i ++) a[i] = read(), mx = max(mx, a[i]), gs[a[i]] ++;
for(int i = 1; i <= mx; i ++)
for(int j = i + i; j <= mx; j += i)
gs[i] += gs[j];
for(int i = 1; i <= mx; i ++) if(gs[i]) {
d[i] = now; now += gs[i];
fa[i] = now; init(i, gs[i]), now += gs[i];
gs[i] = 0;
}
for(int i = 1; i <= n; i ++) {
for(register int j = 1; j * j <= a[i]; j ++) if(a[i] % j == 0) {
d[j][gs[j] ++] = i;
// printf("%d %d %d\n", j, gs[j], d[j][gs[j] - 1]);
if(j * j != a[i]) d[a[i] / j][gs[a[i] / j] ++] = i;
}
update(i, a[i]);
}
ll lst = 0;
while(m --) {
int o, l, r, x;
o = read();
if(o == 1) {
l = read(), r = read(), x = read();
l ^= lst, r ^= lst, x ^= lst;
if(x == 1) continue;
int pos = lower_bound(d[x], d[x] + gs[x], l) - d[x];
// printf("---%d %d %d %d %d \n", pos, fa[x][pos], d[x][pos], get(x, pos), gs[x]);
for(int i = get(x, pos); i < gs[x] && d[x][i] <= r;) {
// printf(" %d\n", i);
if(a[d[x][i]] % x == 0) {
update(d[x][i], a[d[x][i]] / x - a[d[x][i]]);
a[d[x][i]] /= x;
}
if(a[d[x][i]] % x != 0) fa[x][i] = i + 1;
i = get(x, i + 1);
}
} else {
l = read(), r = read();
l ^= lst, r ^= lst;
printf("%lld\n", lst = query(r) - query(l - 1));
}
}
return 0;
}