gcd(x1,x2)=gcd(x1,x2−x1) gcd(xl,xl+1,xl+2⋯xn)=gcd(xl,xl+1−xl,xl+2−xl+1⋯)
-
算法设计
gcd(⋯)线段树维护 [xl⋯xr]+d树状数组维护 -
初始化,令 bi=ai−ai−1
1.1 对差分序列 b[1⋯n] 建立线段树维护 gcd
1.2 同时初始化树状数组 add(tr[⋯],i,bi) -
对于命令 C l r d 用线段树和树状数组同步维护
2.1 树状数组 add(l,d), add(r+1,−d)
2.2 线段树 change(1,l,d), change(1,r+1,−d) -
对于命令 Q l r
al=sum(l),res←query(1,l+1,r)
gcd(al,res) -
坑点,执行 [l,r]+d 的时候,边界条件是 bn+1−d
建线段树的时候,是根据区间 [1,n+1] 来建立线段树
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <bitset>
#include <assert.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
#define Cmp(a, b) memcmp(a, b, sizeof(b))
#define Cpy(a, b) memcpy(a, b, sizeof(b))
#define Set(a, v) memset(a, v, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define _forS(i, l, r) for(set<int>::iterator i = (l); i != (r); i++)
#define _rep(i, l, r) for(int i = (l); i <= (r); i++)
#define _for(i, l, r) for(int i = (l); i < (r); i++)
#define _forDown(i, l, r) for(int i = (l); i >= r; i--)
#define debug_(ch, i) printf(#ch"[%d]: %d\n", i, ch[i])
#define debug_m(mp, p) printf(#mp"[%d]: %d\n", p->first, p->second)
#define debugS(str) cout << "dbg: " << str << endl;
#define debugArr(arr, x, y) _for(i, 0, x) { _for(j, 0, y) printf("%c", arr[i][j]); printf("\n"); }
#define _forPlus(i, l, d, r) for(int i = (l); i + d < (r); i++)
#define lowbit(i) (i & (-i))
#define MPR(a, b) make_pair(a, b)
pair<int, int> crack(int n) {
int st = sqrt(n);
int fac = n / st;
while (n % st) {
st += 1;
fac = n / st;
}
return make_pair(st, fac);
}
inline ll qpow(ll a, int n) {
ll ans = 1;
for(; n; n >>= 1) {
if(n & 1) ans *= 1ll * a;
a *= a;
}
return ans;
}
template <class T>
inline bool chmax(T& a, T b) {
if(a < b) {
a = b;
return true;
}
return false;
}
ll ksc(ll a, ll b, ll mod) {
ll ans = 0;
for(; b; b >>= 1) {
if (b & 1) ans = (ans + a) % mod;
a = (a * 2) % mod;
}
return ans;
}
ll ksm(ll a, ll b, ll mod) {
ll ans = 1 % mod;
a %= mod;
for(; b; b >>= 1) {
if (b & 1) ans = ksc(ans, a, mod);
a = ksc(a, a, mod);
}
return ans;
}
template <class T>
inline bool chmin(T& a, T b) {
if(a > b) {
a = b;
return true;
}
return false;
}
template<class T>
bool lexSmaller(vector<T> a, vector<T> b) {
int n = a.size(), m = b.size();
int i;
for(i = 0; i < n && i < m; i++) {
if (a[i] < b[i]) return true;
else if (b[i] < a[i]) return false;
}
return (i == n && i < m);
}
// ============================================================== //
const int maxn = 500000 + 10;
ll a[maxn], b[maxn];
int n, m;
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll tr[maxn];
void add(int x, ll d) {
for (int i = x; i <= n; i += lowbit(i)) tr[i] += d;
}
ll sum(int x) {
ll res = 0;
for (int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
class A {
public:
int l, r;
ll val;
} t[maxn<<2];
void build(int p, int l, int r) {
t[p].l = l; t[p].r = r;
if (l == r) {
t[p].val = b[l];
return;
}
int mid = (l+r) >> 1;
if (l <= mid) build(p<<1, l, mid);
if (r > mid) build(p<<1 | 1, mid + 1, r);
t[p].val = gcd(t[p<<1].val, t[p<<1 | 1].val);
}
void change(int p, int x, ll d) {
if (x == t[p].l && t[p].r == x) {
t[p].val += d;
return;
}
int mid = (t[p].l + t[p].r) >> 1;
if (x <= mid) change(p<<1, x, d);
if (x > mid) change(p<<1 | 1, x, d);
t[p].val = gcd(t[p<<1].val, t[p<<1 | 1].val);
}
ll query(int p, const int l, const int r) {
if (l > r) return 0;
if (l <= t[p].l && t[p].r <= r) return t[p].val;
int mid = (t[p].l + t[p].r) >> 1;
ll res = 0;
if (l <= mid) res = gcd(res, query(p<<1, l, r));
if (r > mid) res = gcd(res, query(p<<1 | 1, l, r));
return res;
}
void prework() {
for (int i = 1; i <= n; i++) {
add(i, b[i]);
}
build(1, 1, n+1);
}
int main() {
freopen("input.txt", "r", stdin);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
for (int i = 1; i <= n; i++) b[i] = a[i] - a[i-1];
// use tr[...] and seg-tree
prework();
// solve command
while (m--) {
char cmd[2];
scanf("%s", cmd);
if (cmd[0] == 'Q') {
int l, r;
scanf("%d%d", &l, &r);
ll res = query(1, l+1, r);
ll al = sum(l);
res = gcd(al, res);
printf("%lld\n", abs(res));
}
else {
int l, r;
ll d;
scanf("%d%d%lld", &l, &r, &d);
change(1, l, d); change(1, r+1, -d);
add(l, d); add(r+1, -d);
}
}
}
哥们你写的真的简洁,厉害
竞赛大佬太可怕了,头文件这么长
赞