zoukankan      html  css  js  c++  java
  • SCUT

    https://scut.online/p/86

    题意:给5e6个数,选一段最小的[l,r],使得其中的数线性组合可以取遍整数。

    显然当且仅当gcd为1的时候就可以遍历所有整数。

    问题变成怎么求一段连续区间的gcd,可以用队列来尺取。

    但是弹出元素的时候没办法记录逆操作,所以可以用两个栈实现一个队列,只需要满足结合律(像之前网络赛矩阵乘法那题)。

    另一种办法是分治,solve(l,r)表示[l,r]的gcd,顺带更新[l,r]内的gcd为1的最短长度,那么只需要解决跨越中点的区间,记录中点向左推进的各次gcd,然后枚举右端点,每个右端点在左边的gcd中二分出一个最近的距离。这个复杂度感觉爆炸。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 5e6;
    stack<int> st1, st2;
    int g, x[MAXN + 5];
    
    int sumsiz = 0;
    
    void push(int x) {
        if(g == -1) {
            st1.push(x);
            g = x;
        } else {
            st1.push(x);
            g = __gcd(g, x);
        }
        ++sumsiz;
    }
    
    void pop() {
        if(st2.size()) {
            st2.pop();
        } else {
            if(st1.empty())
                exit(-1);
            int tg = st1.top();
            while(st1.size()) {
                st2.push(tg);
                st1.pop();
                if(st1.size())
                    tg = __gcd(tg, st1.top());
            }
            g = -1;
            st2.pop();
        }
        --sumsiz;
    }
    
    int sumg() {
        if(sumsiz == 0)
            return -1;
        if(st2.size()) {
            if(g != -1)
                return __gcd(g, st2.top());
            else
                return st2.top();
        } else
            return g;
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &x[i]);
        }
        bool suc = 0;
        int minlen = MAXN;
        g = -1;
        for(int i = 1; i <= n; ++i) {
            push(x[i]);
            while(sumg() == 1) {
                suc = 1;
                minlen = min(minlen, sumsiz);
                pop();
            }
        }
        if(suc)
            printf("%d
    ", minlen);
        else
            printf("-1");
    }
    
  • 相关阅读:
    (转)Java线程:线程的同步与锁
    (转)线程栈模型与线程的变量、线程状态转换
    (转)概念与原理
    Oracle 技术支持之现场优化的思维路径
    oracle复合索引的选择和使用
    oracle中sql执行性能关注点
    oracle中位图索引和B-tree索引的区别
    oracle锁表
    oracle索引的理解
    oracle海量数据中提升创建索引的速度
  • 原文地址:https://www.cnblogs.com/Inko/p/11693970.html
Copyright © 2011-2022 走看看