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;

正解:分块+并查集

解题报告:

  显然小数据可以直接暴力,对于大数据我们考虑别的方法。

  对于大数据而言我们通过枚举其倍数,如果可以的快速得到大于某个数的最小值那么我们就可以快速得出答案。但是我们考虑要添加数,但是并查集如果维护的是大于某个数的最小值,正着做无法维护,如果是倒着做的话会更有利,因为删除数只需要改变当前数的father即可。所以我们考虑小数据正着暴力,大数据倒着枚举倍数然后查大于当前数的最小值。

  小数据与大数据的分界点在根号处理论上最快,实验表明这道题在300附近是最优的。

 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 100011;
21 const int MAXM = 300011;
22 const int size = 300;
23 int n,father[MAXM],N;
24 bool vis[MAXM];
25 char ch[2];
26 int ans[size+1];
27 struct wen{
28     int type,x;
29     int ans;
30 }q[MAXN];
31
32 inline int getint()
33 {
34        int w=0,q=0;
35        char c=getchar();
36        while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar();
37        if (c==‘-‘)  q=1, c=getchar();
38        while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar();
39        return q ? -w : w;
40 }
41
42 inline int find(int x){
43     if(father[x]!=x) father[x]=find(father[x]);
44     return father[x];
45 }
46
47 inline void work(){
48     n=getint();
49     for(int i=1;i<=size;i++) ans[i]=(1<<30);
50     for(int i=1;i<=n;i++) {
51     scanf("%s",ch); q[i].x=getint();
52     if(ch[0]==‘A‘) { q[i].type=1; vis[q[i].x]=1; N=max(N,q[i].x); for(int j=1;j<=size;j++)  ans[j]=min(ans[j],q[i].x%j);  }
53     else { q[i].type=2; if(q[i].x<=size) q[i].ans=ans[q[i].x]; }
54     }
55     for(int i=1;i<=N;i++) if(vis[i]) father[i]=i; else father[i]=i+1;//father[i]表示大于i的最小值
56     father[N+1]=N+1;
57     for(int i=n;i>=1;i--) {
58     if(q[i].type==1) { father[q[i].x]=q[i].x+1; }//改变原来的值
59     else if(q[i].x>size) {
60         q[i].ans=find(1);
61         for(int j=q[i].x;j<=N;j+=q[i].x) {
62         int lin=find(j);
63         if(lin<=N) q[i].ans=min(lin%q[i].x,q[i].ans);//记得取模
64         else break;
65         }
66     }
67     }
68     for(int i=1;i<=n;i++) if(q[i].type==2) printf("%d\n",q[i].ans);
69 }
70
71 int main()
72 {
73   work();
74   return 0;
75 }
时间: 2024-08-01 10:46:28

BZOJ4320 ShangHai2006 Homework的相关文章

【BZOJ4320】ShangHai2006 Homework 分段+并查集

[BZOJ4320]ShangHai2006 Homework Description 1:在人物集合 S 中加入一个新的程序员,其代号为 X,保证 X 在当前集合中不存在. 2:在当前的人物集合中询问程序员的mod Y 最小的值. (为什么统计这个?因为拯救过世界的人太多了,只能取模) Input 第一行为用空格隔开的一个个正整数 N. 接下来有 N 行,若该行第一个字符为“A” ,则表示操作 1:若为“B”,表示操作 2: 其中 对于 100%的数据:N≤100000, 1≤X,Y≤3000

4320: ShangHai2006 Homework

4320: ShangHai2006 Homework 链接 分析: 分块.对权值模数进行分块,模数小于$\sqrt V$的($V$为权值上界),暴力处理. 模数大于$\sqrt V$的,设模数是k,枚举k的倍数,然后查询大于[k,2k]之间的最小的数x,这个区间的mod k最小的数就是x-k.k的倍数共有$\sqrt V$个,每次查询,再对权值进行分块,并维护后缀最小值,做到$O(1)$查询.复杂度$O(n \sqrt V)$ 代码: #include<cstdio> #include<

【bzoj4320】ShangHai2006 Homework

若Y小于等于sqrt(300000),暴力,对所有的插入的数都更新mn[i]. 若Y大于sqrt(300000),枚举kY,用并查集维护>=i的第一个数,这样只支持删除操作是O(1),然后倒着枚举一边,删除一个数x那么就fa[x]=fa[x+1] #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #inclu

BZOJ 4320 ShangHai2006 Homework

题意: 给出N(<=1e5)个操作,操作分为两种,①在集合中添加一个数x,②问这个集合中mod x 的最小值是多少.(x <= 3e5) 题解: 0.首先我们发现log家族中有算法满足这道题目,那么采用分块的思想. 1.那么对于小于根号下MAX(x)的询问,直接暴力维护答案,对于大于根号MAX(x)的询问,只需要找到第一个大于等于K * x 的值是多少. 2.那么现在问题是维护第一个大于等于K * x 的值是多少,现在有两种选择,①用STL中的<set> 中的 lower_boun

bzoj 4320: ShangHai2006 Homework【分块】

按根号300000=m分情况讨论 查询是,当x小于等于m,那么可以暴力记录直接出解:否则,用分块维护区间值,查询的时候以x为步长跳根号m次取最小值即可 还有一种并查集方法,来自https://www.cnblogs.com/CQzhangyu/p/7088337.html #include<iostream> #include<cstdio> using namespace std; const int N=300010,M=550; int n=300000,m=n/M,q,i,

待 题表

题表 达哥终极杂题表Bzoj2839 hdu6021 Codeforces 804DBzoj2248 hdu5575 Codeforces 786CBzoj2013 bzoj2676 Codeforces 803CBzoj2386 bzoj3782 Codeforces 813DBzoj2699 cogs1667 Codeforces 814DBzoj4798 bzoj2064 Codeforces 814EBzoj4639 bzoj3505 Codeforces 815ABzoj4417 bz

论逗逼的自我修养——乱做计划

我看IOI各种鬼畜题目做做,深知自身姿势水平不足无以抗衡就乱搞一些傻逼题做做. 现在已经跪了0道 [BZOJ3749][POI2015]?asuchy 枚举第一个狗粮被谁吃了,后面的dp就可以了,记录下dp的路径,最后时候验证与假设是否矛盾即可. [BZOJ3750][POI2015]Piecz?? 暴力枚举左上角判断一下. [BZOJ3733][Pa2013]lloczyn 一开始用一个诡异的姿势WA了之后很久没能想出多项式做法,膜了一发鏼之后发现是大(d)法(f)师(s).我们从小到大枚举不

HDU 1789 Doing Homework again(贪心)

Doing Homework again Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadlin

uva 1489 - Math teacher&#39;s homework(数位dp)

题目链接:uva 1489 - Math teacher's homework 题目大意:给定n,k,以及序列m1,m2,-,mn, 要求找到一个长度为n的序列,满足0<=xi<=mi, 并且x1XORx2XOR-XORxn=k 解题思路:数位dp,在网上看了别人的代码,高大上... 假设有二进制数 k : 00001xxxx mi:0001xxxxx, 那么对于xi即可以满足任意的x1XORx2XOR-XORxi?1XORxi+1XOR-XORxn,根据这一点进行数位dp. dp[i][j]