HDU 4630 No Pain No Game(线段树离线处理)
程序员文章站
2022-04-18 13:13:34
题意:给你一个n的全排列, q个操作, 每个操作是一个区间,要求求出这个区间中任意两个数的gcd的最大值。
思路:一个数是两个数的公约数, 等价于一个数可以被两个整数同时整除。...
题意:给你一个n的全排列, q个操作, 每个操作是一个区间,要求求出这个区间中任意两个数的gcd的最大值。
思路:一个数是两个数的公约数, 等价于一个数可以被两个整数同时整除。 所以我们可以算出每一个数的所有约数, 然后求一个区间中被超过两个数整除的数中的最大值即可。
维护区间最大值, 我们可以用线段树来维护。 因为我们难以同时维护一个区间, 所以我们离线处理, 按照r排序, 那么每次如果当前数的一个约数曾经出现过, 就在之前出现的点加入线段树, 每次顺便查询即可。
细节参见代码:
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; typedef long double ld; const ld eps = 1e-9, PI = 3.1415926535897932384626433832795; const int mod = 1000000000 + 7; const int INF = 0x3f3f3f3f; // & 0x7FFFFFFF const int seed = 131; const ll INF64 = ll(1e18); const int maxn = 50000 + 10; int T,n,m,maxv[maxn<<2],a[maxn],pre[maxn],ans[maxn]; struct node { int id, l, r; node(int id=0, int l=0, int r=0):id(id), l(l), r(r) {} bool operator < (const node& rhs) const { return r < rhs.r; } }op[maxn]; void pushup(int o) { maxv[o] = max(maxv[o<<1], maxv[o<<1|1]); } void build(int l, int r, int o) { int m = (l + r) >> 1; maxv[o] = 0; if(l == r) return ; build(l, m, o<<1); build(m+1, r, o<<1|1); } void update(int L, int R, int v, int l, int r, int o) { int m = (l + r) >> 1; if(L <= l && r <= R) { maxv[o] = max(maxv[o], v); return ; } if(L <= m) update(L, R, v, l, m, o<<1); if(m < R) update(L, R, v, m+1, r, o<<1|1); pushup(o); } int query(int L, int R, int l, int r, int o) { int m = (l + r) >> 1; if(L <= l && r <= R) { return maxv[o]; } int ans = 0; if(L <= m) ans = max(ans, query(L, R, l, m, o<<1)); if(m < R) ans = max(ans, query(L, R, m+1, r, o<<1|1)); pushup(o); return ans; } int q, r, l; int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } scanf("%d",&q); for(int i=0;i