zoukankan      html  css  js  c++  java
  • BZOJ 3809 Gty的二逼妹子序列

    Description:

    有一个长度为n的序列, 有一些询问l r a b,表示区间[l,r]中数权值在[a,b]中的数的种类数。

    Solution:

    nsqrt(n)logn的很容易想到,但是会超。

    考虑莫队时如何快速计算答案?把权值分块,块内统计答案,每次询问只需sqrt(n)。

    故总的时间复杂度为nsqrt(n)+msqrt(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, maxm = 1e6+10;
    12 int n, m, a[maxn];
    13 int bel[maxn], l[maxn], r[maxn], s_block;
    14 struct Query
    15 {
    16     int l, r, a, b, id;
    17     void read(int i) { scanf("%d %d %d %d", &l, &r, &a, &b), id = i; }
    18     bool operator < (const Query &AI) const { return bel[l] == bel[AI.l] ? r < AI.r : l < AI.l; }
    19 }q[maxm];
    20 int s[1100], c[maxn], ans[maxm];
    21 
    22 int calc(int x, int y)
    23 {
    24     int L = bel[x], R = bel[y], ret = 0;
    25     if (L == R)
    26     {
    27         REP(i, x, y) if (c[i]) ret ++;
    28     }
    29     else
    30     {
    31         REP(i, L+1, R-1) ret += s[i];
    32         REP(i, x, r[L]) if (c[i]) ret ++;
    33         REP(i, l[R], y) if (c[i]) ret ++;
    34     }
    35     return ret;
    36 } 
    37 
    38 void add(int x) { if (++c[x] == 1) s[bel[x]] ++; }
    39 
    40 void del(int x) { if (--c[x] == 0) s[bel[x]] --; }
    41 
    42 void solve()
    43 {
    44     int now_l = 1, now_r = 0;
    45     REP(i, 1, m)
    46     {
    47         for (; now_r < q[i].r; add(a[++now_r]));
    48         for (; now_l > q[i].l; add(a[--now_l]));
    49         for (; now_r > q[i].r; del(a[now_r--]));
    50         for (; now_l < q[i].l; del(a[now_l++]));
    51         ans[q[i].id] = calc(q[i].a, q[i].b);
    52     }
    53 }
    54 
    55 int main()
    56 {
    57     scanf("%d %d", &n, &m);
    58     REP(i, 1, n) scanf("%d", &a[i]);
    59     int block = int(sqrt(n));
    60     REP(i, 1, n)
    61     {
    62         bel[i] = i/block+1, r[bel[i]] = i;
    63         if (i == 1 || bel[i] != bel[i-1]) l[bel[i]] = i;
    64     }
    65     s_block = n/block+1;
    66     REP(i, 1, m) q[i].read(i);
    67     sort(q+1, q+m+1);
    68     solve();
    69     REP(i, 1, m) printf("%d
    ", ans[i]);
    70     return 0;
    71 }
    View Code

    //if为了省行,少了括号,调了很久

     

     

     

  • 相关阅读:
    ubuntu 更新软件
    如何在linux(lubuntu)下搭建C/C++开发环境
    Linux下如何查看版本信息
    知识点笔记
    Require.js中使用jQuery 插件
    async中常用总结
    node.js在遇到“循环+异步”时的注意事项
    前端性能优化
    生产/消费者问题
    线程与内存
  • 原文地址:https://www.cnblogs.com/-ZZB-/p/6691193.html
Copyright © 2011-2022 走看看