【bzoj4320】ShangHai2006 Homework

*题目描述:
1:在人物集合 S 中加入一个新的程序员,其代号为 X,保证 X 在当前集合中不存在。
2:在当前的人物集合中询问程序员的mod Y 最小的值。 (为什么统计这个?因为拯救
过世界的人太多了,只能取模)
*输入:
第一行为用空格隔开的一个个正整数 N。
接下来有 N 行,若该行第一个字符为“A” ,则表示操作 1;若为“B”,表示操作 2;
其中 对于 100%的数据:N≤100000, 1≤X,Y≤300000,保证第二行为操作 1。
*输出:
对于操作 2,每行输出一个合法答案。
*样例输入:
5
A 3
A 5
B 6
A 9
B 4
*样例输出:
3
1
*提示:
【样例说明】
在第三行的操作前,集合里有 3、5 两个代号,此时 mod 6 最小的值是 3 mod 6 = 3;
在第五行的操作前,集合里有 3、5、9,此时 mod 4 最小的值是 5 mod 4 = 1;
*题解:
我们对于权值分块,小于根号300000的直接记录答案,大于的暴力枚举倍数,维护两个数组,记录某个点的块内的大于它的最小值,和每个块的后面的最小的数,然后每次O(1)查就好了。
*代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

#ifdef WIN32
    #define LL "%I64d"
#else
    #define LL "%lld"
#endif

#ifdef CT
    #define debug(...) printf(__VA_ARGS__)
    #define setfile() 
#else
    #define debug(...)
    #define filename ""
    #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
#endif

#define R register
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1 << 15], *S = B, *T = B;
inline int FastIn()
{
    R char ch; R int cnt = 0; R bool minus = 0;
    while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
    ch == '-' ? minus = 1 : cnt = ch - '0';
    while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
    return minus ? -cnt : cnt;
}
#define maxn 100010
#define maxs 610
#define maxss 300000
int ans[maxs], a[maxn];
int ans1[maxss + 10], ans2[maxs], id[maxss + 10], left[maxs], right[maxs];
int main()
{
//  setfile();
    memset(ans, 63, sizeof(ans));
    memset(ans1, 63, sizeof(ans1));
    memset(ans2, 63, sizeof(ans2));
    R int n = 0;
    R int block = sqrt(maxss);
    for (R int i = 1; i <= maxss; ++i) id[i] = i / block;
    for (R int i = 0; i <= maxss / block; ++i)
        left[i] = i * block, right[i] = (i + 1) * block - 1;
    for (R int q = FastIn(); q; --q)
    {
        R char opt = getc();
        while (opt < 'A' || opt > 'B') opt = getc();
        R int x = FastIn();
        if (opt == 'A')
        {
            a[++n] = x;
            for (R int i = 1; i < maxs; ++i) cmin(ans[i], x % i);
            for (R int i = left[id[x]]; i <= x; ++i) cmin(ans1[i], x);
            for (R int i = id[x] - 1; ~i; --i) cmin(ans2[i], x);
        }
        else
        {
            R int anss = maxss;
            if (x >= maxs)
                for (R int i = 0; i <= maxss; i += x)
                {
                    R int t = dmin(ans1[i], ans2[id[i]]);
                    cmin(anss, t - i);
                }
            else anss = ans[x];
            printf("%d\n", anss );
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值