zoukankan      html  css  js  c++  java
  • bzoj 4320: ShangHai2006 Homework

    4320: ShangHai2006 Homework

    Time Limit: 10 Sec Memory Limit: 128 MB

    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;

    题目分析

    首先,当(Y le sqrt {MaxY}),我们可以暴力更新(ans)数组。当(Y gt sqrt {MaxY})时,我们可以按倍数进行枚举。这样我们就可以保证每次查询都在(O(sqrt Y))以内。

    不过我们在枚举大的(Y)时,还要能迅速求出答案,显然我们需要找到(le k*Y)的最小数,显然可以用set水过。

    #include <set>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    set<int>s;
    set<int>::iterator it;
    int ans[550];
    int main() {
        int i,j,n,a,t,res; char op[3];
        for(scanf("%d",&n),memset(ans,127,sizeof ans),i=0;i<n;++i) {
            scanf("%s%d",op,&a);
            if(*op=='A') {
                for(j=1;j<550;++j) (t=a%j)<ans[j]?ans[j]=t:1;
                s.insert(a);
            } else
                if(a<550) printf("%d
    ",ans[a]);
                else { for(j=0,res=0x7f7f7f7f;j<300001;j+=a) {
                        it=s.lower_bound(j);
                        if(it==s.end()) continue;
                        t=*it%a,t<res?res=t:1;
                    }
                    printf("%d
    ",res);
                }
        }
        return 0;
    }
    

    不过,我们也可以用并查集来求出这个数,而且速度更快。

    #include <cstdio>
    #include <cstring>
    #define M 300005
    #define N 100005
    int fa[M],ans[N],val[N],d[550];
    char op[N],ts[4],mark[M];
    int find(int u) {return (fa[u]^u)?(fa[u]=find(fa[u])):u;}
    void Union(int x,int y) {
        x=find(x),y=find(y);
        (x<y)?fa[x]=y:fa[y]=x;
    }
    int main() {
        int n,i,j,t; memset(d,127,sizeof d);
        for(scanf("%d",&n),i=1;i<=n;++i) {
            scanf("%s%d",ts,val+i);
            if((op[i]=*ts)=='A') {
                for(j=1;j<550;++j) ((t=val[i]%j)<d[j])?d[j]=t:1;
                mark[val[i]]=1;
            } else ans[i]=d[val[i]];
        }fa[300001]=300001;
        for(i=300000;i;--i) (mark[i])?fa[i]=i:fa[i]=find(fa[i+1]);
        for(i=n;i;--i) {
            if(op[i]=='A') Union(val[i],val[i]+1);
            else if(val[i]>=550) {
                t=find(1),ans[i]=(t==300001)?val[i]-1:(t%val[i]);
                for(j=val[i];j<300001;j+=val[i])
                  (((t=find(j))==300001)?t=val[i]-1:t%=val[i]),(t<ans[i])?ans[i]=t:1;
            }
        }
        for(i=1;i<=n;++i)
          if(op[i]=='B') printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    轻轻松松教你写日志-超级简单
    JAVA实现KNN分类
    怎样给filter加入自己定义接口
    设计模式之Visitor模式(笔记)
    Leet Code OJ 237. Delete Node in a Linked List [Difficulty: Easy]
    在C#中怎样推断线程当前所处的状态
    leetCode 83.Remove Duplicates from Sorted List(删除排序链表的反复) 解题思路和方法
    谈谈源码管理那点事儿(一)——源码管理十诫(转)
    安装gi的时候回退root.sh的运行
    Android开发学习之路--异步消息Handler,Message,Looper和AsyncTask之初体验
  • 原文地址:https://www.cnblogs.com/cycleke/p/5956791.html
Copyright © 2011-2022 走看看