zoukankan      html  css  js  c++  java
  • [洛谷P3674]小清新人渣的本愿

    题目传送门

    这道题是一道莫队题。对于每一种问法,就是查询对应的数是否在当前的区间内。

    设$b[i]$表示莫队当前区间中有没有$i$这个数。

    对于第一问“是否可以选出两个数它们的差为x”,也就是判断当$i-j=x$时是否存在$b[i],b[j]=1$。变形一下发现$i=j+x$,就成了$b[j],b[j+x]=1$。

    我们用一个$ ext{bitset}$操作,判断这一问就变成了判断$(b ext{&&} (b<<x))$是否为真。

    对于第二问就是当$i+j=x$时,是否存在$b[i],b[j]=1$。变形下发现

    $$i=x-j$$

    $$i+N=x+N-j$$

    $$i-(x-N)=(N-j)$$

    再开个$b'= ext{bitset}$维护$N-j$,当$j$出现后,$N-j$为$1$。答案即为$((b<<(N-x)) ext{&&} b')$。

    对于第三问发现枚举因数直接判断复杂度不大,暴力解决。

    一开始计算复杂度发现是$O(msqrt{n}+mn)$,$mn$复杂度是由$ ext{bitset}$的与运算贡献的,会炸的。

    但后来了解到$ ext{bitset}$的复杂度要除掉一个$omega$,$omega$为计算机位数,一般为$32/64$。

    所以就能过了。

    下面的代码的写法可能与上面有细微差别,但与上面是等效的。

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define re register
     6 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
     7 #define repd(i, a, b) for (re int i = a; i >= b; --i)
     8 #define maxx(a, b) a = max(a, b);
     9 #define minn(a, b) a = min(a, b);
    10 #define LL long long
    11 #define INF (1 << 30)
    12 
    13 inline int read() {
    14     int w = 0, f = 1; char c = getchar();
    15     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
    16     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
    17     return w * f;
    18 }
    19 
    20 const int maxn = 1e5 + 5;
    21 
    22 bitset<maxn> S1, S2;
    23 
    24 struct Query {
    25     int l, r, id, pos, opt, x;
    26 } q[maxn];
    27 bool cmp(Query a, Query b) { return a.pos < b.pos || a.pos == b.pos && a.r < b.r; }
    28 
    29 int n, m, a[maxn], ans, b[maxn], size, cnt[maxn];
    30 
    31 void del(int x) { cnt[x]--; if (!cnt[x]) S1[x] = S2[n-x] = 0; }
    32 void ins(int x) { if (!cnt[x]) S1[x] = S2[n-x] = 1; cnt[x]++; }
    33 
    34 int main() {
    35     n = read(), m = read();
    36     size = sqrt(n);
    37     rep(i, 1, n) a[i] = read();
    38     rep(i, 1, m) q[i].opt = read(), q[i].l = read(), q[i].r = read(), q[i].x = read(), q[i].id = i, q[i].pos = (q[i].l + size - 1) / size;
    39     sort(q+1, q+m+1, cmp);
    40     int pl = 1, pr = 0;
    41     rep(i, 1, m) {
    42         while (pl < q[i].l) del(a[pl]), pl++;
    43         while (pl > q[i].l) pl--, ins(a[pl]);
    44         while (pr < q[i].r) pr++, ins(a[pr]);
    45         while (pr > q[i].r) del(a[pr]), pr--;
    46         if (q[i].opt == 1) {
    47             b[q[i].id] = ((S1 << q[i].x) & S1).any() ? 1 : 0;
    48         }
    49         else if (q[i].opt == 2) {
    50             b[q[i].id] = ((S2 >> (n-q[i].x)) & S1).any() ? 1 : 0;
    51         }
    52         else if (q[i].opt == 3) {
    53             b[q[i].id] = 0;
    54             rep(x, 1, sqrt(q[i].x))
    55                 if (!(q[i].x % x) && S1[x] && S1[q[i].x/x]) { b[q[i].id] = 1; break; }
    56         }
    57     }
    58     rep(i, 1, m) printf("%s
    ", b[i] ? "hana" : "bi");
    59     return 0;
    60 }
  • 相关阅读:
    教你如何在 Visual Studio 2013 上使用 Github
    如果你也会C#,那不妨了解下F#(1):F# 数据类型
    博客园主题美化
    适配器模式 实战
    mysql in 超过1000 解决方案
    shell: 循环日期+1
    sqoop export 报错:Got exception running Sqoop: org.kitesdk.data.DatasetNotFoundException: Descriptor location does not exist:
    git 回滚到执行版本,并推送到远程分支
    hive表增加字段,并指定字段位置
    微信抢红包架构设计
  • 原文地址:https://www.cnblogs.com/ac-evil/p/10372191.html
Copyright © 2011-2022 走看看