原题点这里
这一题就是简单的语法题加欧几里得算法求gcd,但是优化时间复杂度的方法非常巧妙。
由于q很大,会爆栈,因此要手写栈。
在第 4种操作中,如果暴力每次求最大公约数会TLE,但是加上一句
if (g == 1) break;
1与任何数的最大公约数都是1,所以一但得到1,则立即退出,可以大大降低需要的时间而通过。
这一题的正解应该是使用线段树。待更新…
#include<iostream>
using namespace std;
const int N = 2e5 + 10;
int n;
int stk[N], hh = 0;
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
void push(int x)
{
stk[++hh] = x;
}
void pop()
{
hh--;
}
int top()
{
return stk[hh];
}
void modify(int k)
{
int g = stk[hh];
for (int i = hh - k + 1; i < hh; i++) {
g = gcd(stk[i], g);
if (g == 1) break; // 优化时间复杂度,因为k可能很大,g很容易会变为1,因此可以优化很多
}
for (int i = hh - k + 1; i <= hh; i++) {
stk[i] = g;
}
}
void solve()
{
int q;
scanf("%d", &q);
while (q--) {
int op;
scanf("%d", &op);
if (op == 1) {
int x;
scanf("%d", &x);
push(x);
}
else if (op == 2) {
pop();
}
else if (op == 3) {
printf("%d\n", top());
}
else if (op == 4) {
int k;
scanf("%d", &k);
modify(k);
}
}
}
int main()
{
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}