差分维护 gcd 是一个很常见的技巧了。。
先写个线段树拿点部分分吧。。。(然后发现讨论 n,m 大小。。暴力开 o2 能过。)
#include <lastweapon/io>
// #include <lastweapon/segtree>
using namespace lastweapon;
const int N = int(5e5)+9;
/*
LL gcd(LL a,LL b)
{
return b?gcd(b,a%b):abs(a);
}*/
inline LL gcd(LL a,LL b)
{
if(a<0) a=-a;
if(b<0) b=-b;
if(!a) return b;
if(!b) return a;
LL t=__builtin_ctzll(a|b),tmp;
a>>=__builtin_ctzll(a);
do
{
b>>=__builtin_ctzll(b);
if(a>b)
{
tmp=a,a=b,b=tmp;
}
b-=a;
} while(b);
return a<<t;
}
LL op(LL a, LL b) { return gcd(a, b); }
LL e() { return 0; }
int m, n;
const int TN = 4*N, M = 710;
#define lx (x<<1)
#define rx (lx|1)
#define ml ((l+r)>>1)
#define mr (ml+1)
#define lc lx,l,ml
#define rc rx,mr,r
#define rt 1,0,n-1
struct SegTree{
vector<LL> T;
void add(int x, LL d) {
T[x] += d;
}
void Build(int x, int l, int r, vector<LL> &a) {
if (l < r) {
T[x] = 0;
Build(lc, a), Build(rc, a);
} else {
T[x] = a[l];
}
}
LL Query(int x, int l, int r, const int p) {
if (l == r) {
return T[x];
} else {
return T[x] + (p < mr ? Query(lc, p) : Query(rc, p));
}
}
void Add(int x, int l, int r, const int a, const int b, const LL d) {
if (b < l || r < a) return;
if (a <= l && r <= b) {
add(x, d);
} else {
Add(lc, a, b, d); Add(rc, a, b, d);
}
}
} S[M];
struct SegTree2{
vector<LL> T;
void upd(int x) {
T[x] = gcd(T[lx], T[rx]);
}
void add(int x, LL d) {
T[x] += d;
}
void Build(int x, int l, int r, vector<LL> &a) {
if (l < r) {
Build(lc, a), Build(rc, a);
upd(x);
} else {
T[x] = a[l];
}
}
LL Query(int x, int l, int r, const int a, const int b) {
if (b < l || r < a) return 0;
if (a <= l && r <= b) {
return T[x];
} else {
return gcd(Query(lc, a, b), Query(rc, a, b));
}
}
void Add(int x, int l, int r, const int p, const LL d) {
if (l == r) {
add(x, d);
} else {
if (p < mr) Add(lc, p, d);
else Add(rc, p, d);
upd(x);
}
}
} T[M];
bool flip;
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
RD(m, n); // if (m != 1) return 0;
int y0, x0; RD(y0, x0); --x0; --y0; int Q; RD(Q);
if (m > n) {
swap(m, n);
flip = 1;
}
vector<vector<LL>> a, d; a.resize(m); d.resize(m);
if (flip) {
REP(i, n) REP(j, m) a[j].PB(RD());
} else {
REP(j, m) REP(i, n) a[j].PB(RD());
}
REP(j, m) {
REP(i, n-1) d[j].PB(a[j][i+1] - a[j][i]);
d[j].PB(0);
}
REP(i, m) S[i].T.resize(4*n), S[i].Build(rt, a[i]);
REP(i, m) T[i].T.resize(4*n), T[i].Build(rt, d[i]);
DO(Q) {
int cmd, u, l, d, r; RD(cmd, u, l, d, r);
if (!cmd) {
u = y0 - u; d = y0 + d; l = x0 - l; r = x0 + r;
if (flip) swap(u, l), swap(d, r);
LL z = 0; FOR_1(i, u, d) {
z = gcd(z, gcd(S[i].Query(rt, l), l < r ? T[i].Query(rt, l, r-1) : 0));
}
printf("%lld\n", abs(z));
} else {
LL delta; RD(delta); //continue;
--l; --r; --u; --d; if (flip) swap(u, l), swap(d, r);
FOR_1(i, u, d) {
S[i].Add(rt, l, r, delta);
if (l) T[i].Add(rt, l-1, delta);
T[i].Add(rt, r, -delta);
}
}
}
}




Alca
Amber
Belleve Invis
Chensiting123
Edward_mj
Fotile96
Hlworld
Kuangbin
Liyaos
Lwins
LYPenny
Mato 完整版
Mikeni2006
Mzry
Nagatsuki
Neko13
Oneplus
Rukata
Seter
Sevenkplus
Sevenzero
Shirleycrow
Vfleaking
wangzhpp
Watashi
WJMZBMR
Wywcgs
XadillaX
Yangzhe
三途川玉子
About.me
Vijos
