• BZOJ 4320 ShangHai2006 Homework


    题意:

    给出N(<=1e5)个操作,操作分为两种,①在集合中添加一个数x,②问这个集合中mod x 的最小值是多少。(x <= 3e5)

    题解:

    0.首先我们发现log家族中有算法满足这道题目,那么采用分块的思想。

    1.那么对于小于根号下MAX(x)的询问,直接暴力维护答案,对于大于根号MAX(x)的询问,只需要找到第一个大于等于K * x 的最小值是多少。

    2.那么现在问题是维护第一个大于等于K * x(K为正整数) 的最小值是多少,现在有两种选择,①用STL中的<set> 中的 lower_bound 复杂度为logx  ②用并查集充当链表 复杂度很小

    代码:

    /**************************************************************
        Problem: 4320
        User: xgtao
        Language: C++
        Result: Accepted
        Time:1420 ms
        Memory:7148 kb
    ****************************************************************/
     
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
     
    const int block = 507;
    const int N = 3e5 + 7;
    char ch[2];
    int pa[N], x, q[N], o[N], ans[N], mini[N], n, cnt;
     
    int find (int x) {
        return pa[x] == x ? x : pa[x] = find (pa[x]);
    }
     
    int main () {
        scanf ("%d", &n);
        memset (mini, 127, sizeof mini);
        for (int i = 0; i < N; ++i) pa[i] = i + 1;
        for (int i = 1; i <= n; ++i) {
            scanf ("%s%d", ch, &x);
            if (ch[0] == 'A') {
                o[i] = 1;
                q[i] = x;
                pa[x] = x;
                for (int i = 1; i <= block; ++i) {
                    mini[i] = min (mini[i], x % i);
                }
            }
            else if (ch[0] == 'B') {
                o[i] = 2;
                q[i] = x;
                if (q[i] <= block) ans[i] = mini[q[i]];
            }
        }
        for(int i = N - 1;i >= 0; --i) pa[i] = find(pa[i]);
        for (int i = n; i >= 1; --i) {
            if (o[i] == 1) pa[find (q[i])] = pa[find (q[i] + 1)];
            else if (o[i] == 2) {
                if (q[i] > block) {
                    int ret = 1e9+7;
                    for (int j = 0; j < N; j += q[i]) {
                        if (find (j) == N) continue;
                        ret = min (ret, find(j) % q[i]);
                    }
                    ans[i] = ret;
                    if (ret == 1e9+7) ans[i] = q[i] - 1;
                } 
            }
        }
        for (int i = 1; i <= n; ++i) if (o[i] == 2) printf ("%d
    ", ans[i]);
        return 0;
    }
    

      

      

    总结:

    合理运用并查集当链表的性质QAQ

  • 相关阅读:
    Luogu3119 [USACO15JAN]Grass Cownoisseur G
    BZOJ4361 isn
    洛谷1330 封锁阳光大学
    codechef AUG17 T2 Chef and Mover
    codechef AUG17 T1 Chef and Rainbow Array
    【bzoj3211】花神游历各国&&【bzoj3038】上帝造题的七分钟2
    noip 瑞士轮 ————归并排序解法
    记录string的妙用
    洛谷P1550 [USACO08OCT]打井Watering Hole
    汕头市队赛 SRM 09 C 撕书
  • 原文地址:https://www.cnblogs.com/xgtao/p/5967984.html
Copyright © 2020-2023  润新知