When can an algorithm have square root(n) time complexity?

前端 未结 6 979
攒了一身酷
攒了一身酷 2021-02-01 15:11

Can someone give me example of an algorithm that has square root(n) time complexity. What does square root time complexity even mean?

6条回答
  •  星月不相逢
    2021-02-01 15:45

    Prime numbers

    As mentioned in some other answers, some basic things related to prime numbers take O(sqrt(n)) time:

    1. Find number of divisors
    2. Find sum of divisors
    3. Find Euler's totient

    Below I mention two advanced algorithms which also bear sqrt(n) term in their complexity.

    MO's Algorithm

    try this problem: Powerful array

    My solution:

    #include 
    using namespace std;
    const int N = 1E6 + 10, k = 500;
    
    struct node {
        int l, r, id;
        bool operator<(const node &a) {
            if(l / k == a.l / k) return r < a.r;
            else return l < a.l;
        }
    } q[N];
    
    long long a[N], cnt[N], ans[N], cur_count;
    void add(int pos) {
        cur_count += a[pos] * cnt[a[pos]];
        ++cnt[a[pos]];
        cur_count += a[pos] * cnt[a[pos]];
    }
    void rm(int pos) {
        cur_count -= a[pos] * cnt[a[pos]];
        --cnt[a[pos]];
        cur_count -= a[pos] * cnt[a[pos]];
    }
    
    int main() {
        int n, t;
        cin >> n >> t;
        for(int i = 1; i <= n; i++) {
            cin >> a[i];
        }
        for(int i = 0; i < t; i++) {
            cin >> q[i].l >> q[i].r;
            q[i].id = i;
        }
        sort(q, q + t);
        memset(cnt, 0, sizeof(cnt));
        memset(ans, 0, sizeof(ans));
    
        int curl(0), curr(0), l, r;
        for(int i = 0; i < t; i++) {
            l = q[i].l;
            r = q[i].r;
    
    /* This part takes O(n * sqrt(n)) time */
            while(curl < l)
                rm(curl++);
            while(curl > l)
                add(--curl);
            while(curr > r)
                rm(curr--);
            while(curr < r)
                add(++curr);
    
            ans[q[i].id] = cur_count;
        }
        for(int i = 0; i < t; i++) {
            cout << ans[i] << '\n';
        }
        return 0;
    }
    

    Query Buffering

    try this problem: Queries on a Tree

    My solution:

    #include 
    using namespace std;
    const int N = 2e5 + 10, k = 333;
    
    vector t[N], ht;
    int tm_, h[N], st[N], nd[N];
    inline int hei(int v, int p) {
        for(int ch: t[v]) {
            if(ch != p) {
                h[ch] = h[v] + 1;
                hei(ch, v);
            }
        }
    }
    inline void tour(int v, int p) {
        st[v] = tm_++;
        ht.push_back(h[v]);
        for(int ch: t[v]) {
            if(ch != p) {
                tour(ch, v);
            }
        }
        ht.push_back(h[v]);
        nd[v] = tm_++;
    }
    
    int n, tc[N];
    vector loc[N];
    long long balance[N];
    vector> buf;
    inline long long cbal(int v, int p) {
        long long ans = balance[h[v]];
        for(int ch: t[v]) {
            if(ch != p) {
                ans += cbal(ch, v);
            }
        }
        tc[v] += ans;
        return ans;
    }
    inline void bal() {
        memset(balance, 0, sizeof(balance));
        for(auto arg: buf) {
            balance[arg.first] += arg.second;
        }
        buf.clear();
        cbal(1,1);
    }
    
    int main() {
        int q;
        cin >> n >> q;
        for(int i = 1; i < n; i++) {
            int x, y; cin >> x >> y;
            t[x].push_back(y); t[y].push_back(x);
        }
        hei(1,1);
        tour(1,1);
        for(int i = 0; i < ht.size(); i++) {
            loc[ht[i]].push_back(i);
        }
        vector::iterator lo, hi;
        int x, y, type;
        for(int i = 0; i < q; i++) {
            cin >> type;
            if(type == 1) {
                cin >> x >> y;
                buf.push_back(make_pair(x,y));
            }
            else if(type == 2) {
                cin >> x;
                long long ans(0);
                for(auto arg: buf) {
                    hi = upper_bound(loc[arg.first].begin(), loc[arg.first].end(), nd[x]);
                    lo = lower_bound(loc[arg.first].begin(), loc[arg.first].end(), st[x]);
                    ans += arg.second * (hi - lo);
                }
                cout << tc[x] + ans/2 << '\n';
            }
            else assert(0);
    
            if(i % k == 0) bal();
        }
    }
    

提交回复
热议问题