Array Stabilization (GCD version) ST表/线段树+二分
作者:互联网
Array Stabilization (GCD version)
题目大意:
每次用
g
c
d
(
a
i
,
a
i
+
1
)
gcd(a_i,a_{i+1})
gcd(ai,ai+1)替换
a
i
a_i
ai(其中n+1视为1),问几次能让数组全部相等。
由规则来看
k=0时,
a
i
=
a
i
a_i=a_i
ai=ai
k=1时,
a
i
=
g
c
d
(
a
i
,
a
i
+
1
)
a_i=gcd(a_i,a_{i+1})
ai=gcd(ai,ai+1)
k=2时,
a
i
=
g
c
d
(
g
c
d
(
a
i
,
a
i
+
1
)
,
g
c
d
(
a
i
+
1
,
a
i
+
2
)
)
=
g
c
d
(
a
i
,
a
i
+
1
,
a
i
+
2
)
a_i=gcd(gcd(a_i,a_{i+1}),gcd(a_{i+1},a_{i+2}))=gcd(a_i,a_{i+1},a_{i+2})
ai=gcd(gcd(ai,ai+1),gcd(ai+1,ai+2))=gcd(ai,ai+1,ai+2)
可以用线段树。
又由于是静态,也可以用ST表。
ST表代码(265ms)
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a));
//#define int ll
using namespace std;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch<'0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 10;
int a[maxn * 2];
int dp[maxn * 2][21];
int Log2[maxn * 2] = {};
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a%b);
}
void init_Log()
{
for (int i = 2; i < maxn * 2; i++)
{
Log2[i] = Log2[i / 2] + 1;
}
}
int n;
void init_ST()
{
for (int i = 1; i <= 2 * n; i++)
{
dp[i][0] = a[i];
}
for (int j = 1; j <= Log2[n * 2]; j++)
{
for (int i = 1; i + (1 << j) - 1 <= 2 * n; i++)
{
dp[i][j] = gcd(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
}
}
}
int ST_query(int l, int r)
{
int len = (r - l + 1);
int k = Log2[len];
int ret = gcd(dp[l][k], dp[r - (1 << k) + 1][k]);
return ret;
}
bool check(int x)
{
int ans = ST_query(1, 1 + x);
for (int i = 1; i + x <= 2 * n; i++)
{
int temp = ST_query(i, i + x);
if (temp != ans)
return 0;
}
return 1;
}
int main()
{
init_Log();
int t;
t = read();
while (t--)
{
n = read();
for (int i = 1; i <= n; i++)
{
a[i] = read();
a[i + n] = a[i];
}
init_ST();
int l = -1, r = n + 1;
while (r - l > 1)
{
int mid = (l + r) / 2;
if (check(mid))
{
r = mid;
}
else
{
l = mid;
}
}
printf("%d\n", r);
}
}
线段树代码(1201ms)
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a));
//#define int ll
using namespace std;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch<'0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 10;
int n;
int a[maxn * 2];
int tree[maxn * 2 * 4];
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a%b);
}
void pushup(int rt)
{
tree[rt] = gcd(tree[rt * 2], tree[rt * 2 + 1]);
}
void build(int rt, int l, int r)
{
if (l == r)
{
tree[rt] = a[l];
return;
}
int mid = (l + r) / 2;
build(rt * 2, l, mid);
build(rt * 2 + 1, mid + 1, r);
pushup(rt);
}
int query(int rt, int l, int r, int L, int R)
{
if (L <= l && r <= R)
{
return tree[rt];
}
int mid = (l + r) / 2;
if (R <= mid)
return query(rt * 2, l, mid, L, R);
else if ((L <= mid) && (mid + 1 <= R))
{
return gcd(query(rt * 2, l, mid, L, mid), query(rt * 2 + 1, mid + 1, r, mid + 1, R));
}
else
return query(rt * 2 + 1, mid + 1, r, L, R);
}
bool check(int x)
{
int len = x + 1;
int ans = query(1, 1, n, 1, 1 + len - 1);
for (int i = 1; i + len - 1 <= 2 * n; i++)
{
int temp = query(1, 1, 2 * n, i, i + len - 1);
if (ans != temp)
return 0;
}
return 1;
}
int main()
{
int t;
t = read();
while (t--)
{
n = read();
for (int i = 1; i <= n; i++)
{
a[i] = read();
a[i + n] = a[i];
}
build(1, 1, 2 * n);
int l = -1, r = n + 1;
while (r - l > 1)
{
int mid = (l + r) / 2;
if (check(mid))
{
r = mid;
}
else
{
l = mid;
}
}
printf("%d\n", r);
}
}
标签:ch,Stabilization,gcd,int,mid,ST,ai,include,GCD 来源: https://blog.csdn.net/qq_51509008/article/details/118722240