【bzoj4320】【ShangHai2006 Homework】【并查集+离线处理】

ShangHai2006 Homework

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 918  Solved: 460
[Submit][Status][Discuss]

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; 

1.插入一个数X 
2.询问所有数 mod Y的最小值

将询问按照Y3105−−−−−√Y>3105−−−−−√两种分类

Y3105−−−−−√:开一个数组ansY代表当询问为Y的时候的答案,每插入一个数枚举1i3105−−−−−√X mod i更新ansi

Y>3105−−−−−√:枚举Y的倍数kY,对于每个kY我们需要找到集合中大于等于kY的数中最小的那个 
log系列显然会T 
考虑并查集,类似于花神游历各国那个题一样,我们可以利用并查集完成【删除一个数,迅速找到一个位置后面第一个没有被删除的数】 
但是这个题是插入一个数啊? 
倒着做就行了

 1 #include<cstring>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdio>
 6 
 7 #define T 300007
 8 #define B 507
 9 #define M 300007
10 #define ll long long
11 using namespace std;
12 inline int read()
13 {
14     int x=0,f=1;char ch=getchar();
15     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
16     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
17     return x*f;
18 }
19 
20 int n;
21 int fa[M],opt[M],num[M];
22 int mn[M],ans[M];
23 
24 int find(int x)
25 {
26     return fa[x]==x?fa[x]:fa[x]=find(fa[x]);
27 }
28 int main()
29 {
30     scanf("%d",&n);
31     memset(mn,127,sizeof(mn));
32     for(int i=1;i<=T;i++)fa[i]=i+1;
33     for(int i=1;i<=n;i++)
34     {
35         char s[5]; 
36         scanf("%s%d",s,&num[i]);
37         opt[i]=s[0]-'A';
38         if(opt[i]==0)
39         {
40             for(int j=1;j<=B;j++)
41                 mn[j]=min(mn[j],num[i]%j);
42             fa[num[i]]=num[i];
43         }
44         else if(num[i]<=B) ans[i]=mn[num[i]];
45     }
46     for(int i=n;i;i--)
47     {
48         if(opt[i]==0)
49             fa[num[i]]=fa[num[i]+1];
50         else if(num[i]>B)
51         {
52             ans[i]=find(1)%num[i];
53             for(int j=num[i];j<=T;j+=num[i])
54             {
55                 int x=find(fa[j]);
56                 if(x)ans[i]=min(ans[i],x%num[i]);
57             }
58         }
59     }
60     for(int i=1;i<=n;i++)
61         if(opt[i]==1)
62             printf("%d
",ans[i]);
63 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8168755.html