• P4688 [Ynoi2016]掉进兔子洞


    P4688 [Ynoi2016]掉进兔子洞

    https://www.luogu.org/problemnew/show/P4688

    分析:

      莫队+bitset。

      一个询问的答案就是 (r1-l1+1) + (r2-l2+1) + (r3-l3+1) - 三个区间都有的元素的个数。

      前面一块可以直接求,后面的考虑莫队。我们可以用bitset来实现查询三个区间都出现的个数。但是每个区间内不保证数字都不一样,如果出现了相同的数字,可以依次在bitset中排开,例如12223,在bitset中的坐标就是12345,所以在离散化的时候只要不去重就行了,然后在增加删除一个数的时候,这个数的位置就是离散化后的坐标+前面有多少相同的数。注意,区间的位置移动的时候,要先加再减,如果先减,可能先使cnt变成了负数,然后再变成正数,那么birset可能访问无效内存,从而使得RE。

      然后发现空间可能会MLE,于是考虑分块处理询问,每个处理询问25000个,然后处理4次。

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<cctype>
     7 #include<set>
     8 #include<vector>
     9 #include<queue>
    10 #include<map>
    11 #include<bitset>
    12 using namespace std;
    13 typedef long long LL;
    14 
    15 inline int read() {
    16     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    17     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    18 }
    19 
    20 const int N = 100000;
    21 const int T = 25000;
    22 
    23 int a[N + 5], b[N + 5], bel[N + 5], cnt[N + 5], ans[T + 5];
    24 bool vis[T + 5];
    25 bitset<N + 5> f[T + 5], g;
    26 
    27 struct Que{
    28     int l, r, id;
    29 }q[T * 3 + 5];
    30 
    31 bool cmp(Que A, Que B) {
    32     if (bel[A.l] == bel[B.l]) return A.r < B.r;
    33     return bel[A.l] < bel[B.l];
    34 }
    35 void add(int p) {
    36     int x = a[p];
    37     cnt[x] ++;
    38     g[x + cnt[x] - 1] = 1;
    39 }
    40 void del(int p) {
    41     int x = a[p];
    42     g[x + cnt[x] - 1] = 0;
    43     cnt[x] --;
    44 }
    45 void solve(int m) {
    46     memset(vis, false, sizeof(vis));
    47     memset(ans, 0, sizeof(ans));
    48     memset(cnt, 0, sizeof(cnt));
    49     int n = 0;
    50     for (int i=1; i<=m; ++i) {
    51         q[++n].id = i, q[n].l = read(), q[n].r = read(); 
    52         ans[i] += q[n].r - q[n].l + 1;
    53         
    54         q[++n].id = i, q[n].l = read(), q[n].r = read();
    55         ans[i] += q[n].r - q[n].l + 1;
    56         
    57         q[++n].id = i, q[n].l = read(), q[n].r = read();
    58         ans[i] += q[n].r - q[n].l + 1;
    59     }
    60     sort(q + 1, q + n + 1, cmp);
    61     g.reset();
    62     int L = 1, R = 0;
    63     for (int i=1; i<=n; ++i) {
    64         // 让add在前,如果del在前,可能会使cnt变成负数,使bitset访问无效内存,RE 
    65         while (L > q[i].l) add(--L); 
    66         while (R < q[i].r) add(++R);
    67         while (L < q[i].l) del(L++);
    68         while (R > q[i].r) del(R--);
    69         if (!vis[q[i].id]) f[q[i].id] = g, vis[q[i].id] = 1;
    70         else f[q[i].id] &= g;
    71     }
    72     for (int i=1; i<=m; ++i) {
    73         ans[i] -= f[i].count() * 3;
    74         printf("%d
    ",ans[i]);
    75     }
    76 }
    77 int main() {
    78     int n = read(), m = read();
    79     int B = sqrt(n);
    80 
    81     for (int i=1; i<=n; ++i) a[i] = read(), b[i] = a[i], bel[i] = (i - 1) / B + 1;
    82     sort(b + 1, b + n + 1);
    83     for (int i=1; i<=n; ++i) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
    84     
    85     while (m) {
    86         if (m < T) solve(m), m = 0;
    87         else solve(T), m -= T;
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    django框架之有名分组、无名分组、路由分发、反向解析等相关内容-62
    django框架之请求生命周期及ORM引入等相关内容-61
    django框架之目录介绍等相关内容-60
    django框架之引入及基础介绍等相关内容-59
    前端之JavaScript练习等相关内容-58
    django之jwt多方式登陆及多表群操作增删改查等相关内容-90
    Linux基础之虚拟机创建、网卡激活、切换YUM源及用户级别等相关内容-92
    django框架之auth组件等相关内容-76
    django框架之单表查询等相关内容-67
    自律
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9626184.html
Copyright © 2020-2023  润新知