给定序列
挺好的一道水题,有一道类似的题,AcWing 246 区间最大公约数,简而言之就是实现区间加,区间求
首先有一个性质,更相减损术,即
然后不难发现可以通过更相减损术,对这个矩形横向进行差分:
发现除了最初始的位置,剩下的每一列都是相同的,所以我们不难想到,除了第一行第一列之外的数,会因为重复所以可以不用考虑。同时对于对应的第一列,也可以差分。最后就可以变成,对于一段查询,求的是序列
然后考虑如何快速维护区间的
xxxxxxxxxx81123
45678910
11using namespace std;12
13mt19937 rnd(random_device{}());14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}15bool rnddd(int x){return rndd(1, 100) <= x;}16
17typedef unsigned int uint;18typedef unsigned long long unll;19typedef long long ll;20typedef long double ld;21
2223
24template < typename T = int >25inline T read(void);26
27int N, Q;28int A[MAXN], B[MAXN], dA[MAXN], dB[MAXN];29
30class SegTree{31private:32 int tr[MAXN << 2];33 34 35 36public:37 void Pushup(int p){tr[p] = __gcd(tr[LS], tr[RS]);}38 void Build(bool flag, int p = 1, int gl = 1, int gr = N){//true - line(y), false - row(x)39 if(gl == gr)return tr[p] = flag ? dB[gl] : dA[gl], void();40 Build(flag, LS, gl, MID), Build(flag, RS, MID + 1, gr);41 Pushup(p);42 }43 int Query(int l, int r, int p = 1, int gl = 1, int gr = N){44 if(l <= gl && gr <= r)return tr[p];45 if(r <= MID)return Query(l, r, LS, gl, MID);46 if(l >= MID + 1)return Query(l, r, RS, MID + 1, gr);47 return __gcd(Query(l, r, LS, gl, MID), Query(l, r, RS, MID + 1, gr));48 }49}stLine, stRow;50
51int main(){52 N = read(), Q = read();53 for(int i = 1; i <= N; ++i)A[i] = read(), dA[i] = A[i] - A[i - 1];54 for(int i = 1; i <= N; ++i)B[i] = read(), dB[i] = B[i] - B[i - 1];55 stLine.Build(true), stRow.Build(false);56 while(Q--){57 int h1 = read(), h2 = read(), w1 = read(), w2 = read();58 int ans = A[h1] + B[w1];59 if(w1 != w2)ans = __gcd(ans, stLine.Query(w1 + 1, w2));60 if(h1 != h2)ans = __gcd(ans, stRow.Query(h1 + 1, h2));61 printf("%d\n", abs(ans));62 }63 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);64 return 0;65}66
67template < typename T >68inline T read(void){69 T ret(0);70 int flag(1);71 char c = getchar();72 while(c != '-' && !isdigit(c))c = getchar();73 if(c == '-')flag = -1, c = getchar();74 while(isdigit(c)){75 ret *= 10;76 ret += int(c - '0');77 c = getchar();78 }79 ret *= flag;80 return ret;81}update-2022_12_06 初稿