zoukankan      html  css  js  c++  java
  • BZOJ4320: ShangHai2006 Homework

    Description

      1:在人物集合 S 中加入一个新的程序员,其代号为 X,保证 X 在当前集合中不存在。 
      2:在当前的人物集合中询问程序员的mod Y 最小的值。 (为什么统计这个?因为拯救
    过世界的人太多了,只能取模) 
     

    Input

    第一行为用空格隔开的一个个正整数 N。 
    接下来有 N 行,若该行第一个字符为“A” ,则表示操作 1;若为“B”,表示操作 2; 
    其中 对于 100%的数据:N≤100000, 1≤X,Y≤300000,保证第二行为操作 1。 
     

    Output

    对于操作 2,每行输出一个合法答案。 
     
     

    Sample Input

    5
    A 3
    A 5
    B 6
    A 9
    B 4

    Sample Output

    3
    1

    HINT

    【样例说明】 

      在第三行的操作前,集合里有 3、5 两个代号,此时 mod 6 最小的值是 3 mod 6 = 3; 

      在第五行的操作前,集合里有 3、5、9,此时 mod 4 最小的值是 5 mod 4 = 1; 

    按权值分块,<=sqrt(300000)的答案直接爆算,>sqrt(300000)的答案可以枚举x/Y的整数部分。

    那么问题就是如何快速计算>x的最小的数并带插入。

    注意快速计算>x的最小的数并带删除可以用并查集来做,那么时光倒流一下就行了。

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=300010;
    const int maxm=100010;
    int pa[maxn],vis[maxn];
    int A[maxm],type[maxm],res[410],ans[maxm];
    inline int findset(int x) {return !pa[x]||x==pa[x]?x:pa[x]=findset(pa[x]);}
    int main() {
        int SIZE=400;
        rep(i,1,SIZE) res[i]=1e9;
        int n=read();
        rep(i,1,n) {
            char s[2];int x;
            scanf("%s%d",s,&x);
            if(s[0]=='A') {
                type[i]=1;vis[x]=1;A[i]=x;
                rep(i,1,SIZE) res[i]=min(res[i],x%i);
            }
            else {
                if(x<=SIZE) ans[i]=res[x];
                else type[i]=2,A[i]=x;
            }
        }
        rep(i,1,300000) if(!vis[i]) pa[i]=i+1;
        dwn(i,n,1) if(type[i]) {
            if(type[i]==1) pa[A[i]]=A[i]+1;
            else {
                ans[i]=1e9;
                for(int j=0;j<=300000;j+=A[i]) {
                    int x=findset(max(1,j));
                    if(x<=300000) ans[i]=min(ans[i],x%A[i]);
                }
            }
        }
        rep(i,1,n) if(type[i]!=1) printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    Spring@Profile注解
    day 32 子进程的开启 及其用法
    day 31 udp 协议SOCK_DGRAM
    day 30 客户端获取cmd 命令的步骤
    day 29 socket 理论
    day 29 socket 初级版
    有关 组合 继承
    day 27 多态 接口 类方法 静态方法 hashlib 摘要算法模块
    新式类和经典类的区别
    day 28 hasattr getattr serattr delattr 和带__内置__ 类的内置方法
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4986712.html
Copyright © 2011-2022 走看看