zoukankan      html  css  js  c++  java
  • BZOJ 2821作诗(Poetize) 分块

    Description

    有一个长度为n的序列,序列每个元素的范围[1,c],有m个询问x y,表示区间[x,y]中出现正偶数次的数的种类数。

    Solution

    大力分块解决问题。

    把序列分块,f[i][j]表示第i块到第j块的答案,并记录块的前缀数的出现次数。

    f[i][j]直接暴力算,块的前缀数的出现次数也可以直接算,都是nsqrt(n)。

    遇到询问x y,中间答案的块可以直接统计,然后再暴力统计左右两边零碎的贡献,也是nsqrt(n)。

    Code

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <string>
     5 #include <algorithm>
     6 #include <cmath>
     7 
     8 using namespace std;
     9 
    10 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    11 const int maxn = 1e5+10;
    12 int n, c, m, a[maxn];
    13 int bel[maxn], l[maxn], r[maxn];
    14 int cnt[350][maxn], s_block, t[maxn], f[350][350];
    15 
    16 int solve(int x, int y)
    17 {
    18     int L = bel[x], R = bel[y];
    19     if (L == R)
    20     {
    21         REP(i, x, y) t[a[i]] = 0;
    22         int ret = 0;
    23         REP(i, x, y) if (t[a[i]] ++) ret += (t[a[i]]&1) ? -1 : 1;
    24         return ret;
    25     }
    26     else
    27     {
    28         int ret = f[L+1][R-1];
    29         REP(i, x, r[L]) t[a[i]] = 0;
    30         REP(i, l[R], y) t[a[i]] = 0;
    31         REP(i, x, r[L]) if (!t[a[i]]) t[a[i]] = cnt[R-1][a[i]]-cnt[L][a[i]];
    32         REP(i, l[R], y) if (!t[a[i]]) t[a[i]] = cnt[R-1][a[i]]-cnt[L][a[i]];
    33         REP(i, x, r[L]) if (t[a[i]] ++) ret += (t[a[i]]&1) ? -1 : 1;
    34         REP(i, l[R], y) if (t[a[i]] ++) ret += (t[a[i]]&1) ? -1 : 1;
    35         return ret;
    36     }
    37 }
    38 
    39 int main()
    40 {
    41     scanf("%d %d %d", &n, &c, &m);
    42     REP(i, 1, n) scanf("%d", &a[i]);
    43     int block = int(sqrt(n));
    44     REP(i, 1, n)
    45     {
    46         bel[i] = i/block+1, r[bel[i]] = i;
    47         if (i == 1 || bel[i] != bel[i-1]) l[bel[i]] = i;
    48     }
    49     s_block = n/block+1;
    50     REP(i, 1, s_block)
    51     {
    52         REP(j, 1, c) t[j] = 0;
    53         REP(j, i, s_block)
    54         {
    55             f[i][j] = (j == i) ? 0 : f[i][j-1];
    56             REP(k, l[j], r[j]) if (t[a[k]] ++) f[i][j] += (t[a[k]]&1) ? -1 : 1;
    57         }
    58     }
    59     REP(i, 1, s_block)
    60     {
    61         REP(j, 1, c) cnt[i][j] = cnt[i-1][j];
    62         REP(j, l[i], r[i]) cnt[i][a[j]] ++;
    63     }
    64     int x, y, ans = 0;
    65     while (m --)
    66     {
    67         scanf("%d %d", &x, &y);
    68         x = (x+ans)%n+1, y = (y+ans)%n+1;
    69         if (x > y) swap(x, y);
    70         printf("%d
    ", ans = solve(x, y));
    71     }
    72     return 0;
    73 }
    View Code

     

     

  • 相关阅读:
    JavaScript之Math和date
    JavaScript之ES5和String
    JavaScript之数组
    JavaScript之 函数
    JavaScript之循环语句
    movies.js
    Js内存存放机制
    Web框架
    css中那些属性是可以继承的?
    赋值运算
  • 原文地址:https://www.cnblogs.com/-ZZB-/p/6690726.html
Copyright © 2011-2022 走看看