卧薪尝胆,厚积薄发。
ShangHai2006 Homework
Date: Wed Jul 18 23:19:40 CST 2018 In Category: NoCategory

Description:

$1$ :在人物集合 $S$ 中加入一个新的程序员,其代号为 $X$ ,保证 $X$ 在当前集合中不存在。
$2$ :在当前的人物集合中询问程序员的 $mod\ Y$ 最小的值。
$N \le 100000$ $X \le 300000$

Solution:

首先把询问分为 $Y$ 大于 $\sqrt{300000}$ ,和 $Y$ 小于 $\sqrt{300000}$ ,用一个数组记录一下 $[1,\sqrt{300000}]$ 的答案。碰到这样的询问就直接输出。对于大于 $\sqrt{300000}$ 的询问,我们离线处理。把加点改成删点。每次询问相当于询问当前数集中比 $Y$ 或 $Y$ 的倍数大并且距离最近的数。很显然可以用并查集处理,把空格都连起来。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n;
#define MAXN 100010
struct change
{
bool type;
int val;
int ans;
}c[MAXN];
inline bool get()
{
register char c = getchar();
while(c != 'A' && c != 'B')c = getchar();
return (c == 'A');
}
inline int read()
{
register int res = 0;
register char c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res;
}
#define MAXB 333
int ans1[MAXB];
#define MAXK 300010
int tag[MAXK];
int f[MAXK];
int find(int x){return (x == f[x] ? x : f[x] = find(f[x]));}
int main()
{
scanf("%d",&n);
memset(ans1,0x3f,sizeof(ans1));
for(int i = 1;i <= n;++i)
{
c[i].type = get();
c[i].val = read();
if(c[i].type)
{
for(int k = 1;k < MAXB;++k)ans1[k] = min(ans1[k],c[i].val % k);
tag[c[i].val] = 1;
}
else
{
if(c[i].val < MAXB)
{
c[i].ans = ans1[c[i].val];
}
}
}
for(int i = 0;i <= 300000;++i)
{
if(tag[i])f[i] = i;
else f[i] = i + 1;
}
f[300001] = 300001;
for(int i = n;i >= 1;--i)
{
if(c[i].type)
{
f[c[i].val] = c[i].val + 1;
}
else
{
if(c[i].val >= MAXB)
{
c[i].ans = 0x3f3f3f3f;
for(int k = 0;c[i].val * k <= 300000;++k)
{
if(find(c[i].val * k) <= 300000)
{
c[i].ans = min(c[i].ans,find(c[i].val * k) - c[i].val * k);
}
}
}
}
}
for(int i = 1;i <= n;++i)
{
if(!c[i].type)
{
printf("%d\n",c[i].ans);
}
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡