传送门
题意:给你一个数组含有n个数,同时进行q次操作,每次操作让x位置上的数乘上v,每次操作后输出给个数组的gcd。
最大公约数:
于是我们有这样的想法,对于每个素数,我们维护n个数中的最小值。显然区间最小值可以用线段树维护,但那样我们不是要开s课线段树?内存显然不够用。
1.考虑离线处理 每次算乘上这个数后对结果的贡献(指数是相加的),同样对于刚开始的n个数,我们可以看作最开始每个数都是1,然后依次乘上ai。
每次算贡献 我们可以一次把所有p的贡献算完,算完后再清空线段树就可以重复利用了。
#include<bits/stdc++.h>
using namespace std;
#define lsn (u << 1)
#define rsn (u << 1 | 1)
#define mid (l + r >> 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
typedef pair<double, double> PD;
const int MAXN = 2e5 + 10;
const int MAX_LEN = 100000 + 10;
const int MAX_LOG_V = 22;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-7;
const ull B = 100000007;
int n, q;
struct Node {
int id, t, v;
};
vector<Node> a[MAXN];
int tr[4*MAXN];
ll ans[2*MAXN];
ll qpow(ll x, int y) {
ll res = 1;
while(y) {
if(y & 1) res = res * x % mod;
y >>= 1;
x = x * x % mod;
}
return res;
}
void pushup(int u) {
tr[u] = min(tr[lsn], tr[rsn]);
}
void add(int u, int l, int r, int p, int v) {
if(l == r && l == p) tr[u] += v;
else {
if(p <= mid) add(lsn, l, mid, p, v);
else add(rsn, mid+