• Educational Codeforces Round 22 E. Army Creation 主席树 或 分块


    http://codeforces.com/contest/813/problem/E

    题目大意:

    给出长度为n的数组和k,  大小是1e5级别。 

    要求在线询问区间[l, r]权值,  权值定义为对于所有不同元素x在区间出现的次数和, 如果x出现次数>k, 那么按k算。

     

     

    重要转换: 考虑一个区间[L, R]的某个数A[i], 它对答案有贡献 当且仅当 它前面与他权值相同的数中第k个数的位置(记为B[i]) < L

    预处理B[], 每次询问就转化为 区间[L, R]中有多少个B[i] < L  

    可以用主席树 或者 分块解决。

    也可以用此题的方法求区间不同元素个数, 其实就是k = 1的情况。

     

    主席树代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <map>
     8 #include <queue>
     9 using namespace std;
    10  
    11 typedef long long ll;
    12  
    13 #define N 100050
    14 const int INF = 1 << 30;
    15 const double pi = acos(-1);
    16 
    17 int pt;
    18 int a[N], b[N], root[N], lc[N * 60], rc[N * 60], cnt[N * 60];
    19 vector<int> lis[N];
    20 
    21 int Add(int y, int l, int r, int v)
    22 {
    23     int x = ++pt;
    24     cnt[x] = cnt[y] + 1;
    25     if (l < r)
    26     {
    27         int mid = (l + r) >> 1;
    28         if (v <= mid) 
    29         {
    30             rc[x] = rc[y];
    31             lc[x] = Add(lc[y], l, mid, v);
    32         }
    33         else
    34         {
    35             lc[x] = lc[y];
    36             rc[x] = Add(rc[y], mid + 1, r, v);
    37         }
    38     }
    39     return x;
    40 }
    41 
    42 int Query(int x, int y, int L, int R, int l, int r)
    43 {
    44     //cout << L <<" " << R << " " << cnt[x] << " " << cnt[y] << endl;
    45     if (l > R || r < L) return 0;
    46     if (l <= L && r >= R) return cnt[x] - cnt[y];
    47     
    48     int Mid = (L + R) >> 1;
    49     return Query(lc[x], lc[y], L, Mid, l, r) + Query(rc[x], rc[y], Mid + 1, R, l, r);
    50 }
    51 
    52 int main()
    53 {
    54     //freopen("in.in", "r", stdin);
    55     //freopen("out.out", "w", stdout);
    56  
    57      int n, k, Q, lastans = 0, l, r;
    58     scanf("%d %d", &n, &k);
    59     for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), lis[a[i]].push_back(i);
    60     
    61     for (int i = 1; i <= 100000; ++i)
    62     {
    63         if (lis[i].size() <= k) continue;
    64         for (int j = k; j < lis[i].size(); ++j) b[lis[i][j]] = lis[i][j - k];
    65     }
    66     
    67     root[0] = ++pt;
    68     for (int i = 1; i <= n; ++i) root[i] = Add(root[i - 1], 0, n, b[i]);
    69     
    70 
    71     scanf("%d", &Q);
    72     while (Q--)
    73     {
    74         scanf("%d %d", &l, &r);
    75         l = (l + lastans) % n + 1;
    76         r = (r + lastans) % n + 1;
    77         if (l > r) swap(l, r);
    78         lastans = Query(root[r], root[l - 1], 0, n, 0, l - 1);
    79         printf("%d
    ", lastans);
    80     }
    81      
    82     return 0;
    83 } 
    View Code

     

    分块代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <map>
     8 #include <queue>
     9 using namespace std;
    10  
    11 typedef long long ll;
    12  
    13 #define N 100050
    14 const int INF = 1 << 30;
    15 const double pi = acos(-1);
    16 
    17 int pt;
    18 int a[N], b[N], id[N], dp[350][N];
    19 int bl[350], br[350];
    20 vector<int> lis[N];
    21 
    22 int main()
    23 {
    24     //freopen("in.in", "r", stdin);
    25     //freopen("out.out", "w", stdout);
    26  
    27      int n, k, Q, lastans = 0, l, r;
    28     scanf("%d %d", &n, &k);
    29     for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), lis[a[i]].push_back(i);
    30     
    31     for (int i = 1; i <= 100000; ++i)
    32     {
    33         if (lis[i].size() <= k) continue;
    34         for (int j = k; j < lis[i].size(); ++j) b[lis[i][j]] = lis[i][j - k];
    35     }
    36     
    37     int block = (int)sqrt(n + 1);
    38     
    39     for (int i = 1; ; ++i)
    40     {
    41         l = (i - 1) * block + 1;
    42         r = min(n, l + block - 1);
    43         bl[i] = l, br[i] = r;
    44         for (int j = l; j <= r; ++j) dp[i][b[j]]++, id[j] = i;
    45         for (int j = 1; j <= 100000; ++j) dp[i][j] += dp[i][j - 1];
    46         if (r == n) break;
    47     }
    48      
    49      scanf("%d", &Q);
    50      while (Q--)
    51      {
    52          scanf("%d %d", &l, &r);
    53           l = (l + lastans) % n + 1;
    54           r = (r + lastans) % n + 1;
    55           if (l > r) swap(l, r);
    56 
    57           int res = 0;
    58           if (id[l] == id[r])
    59           {
    60               for (int i = l; i <= r; ++i) 
    61                   res += b[i] < l;
    62         }
    63         else
    64         {
    65             for (int i = l; i <= br[id[l]]; ++i) res += b[i] < l;
    66             for (int i = bl[id[r]]; i <= r; ++i) res += b[i] < l;
    67             for (int i = id[l] + 1; i <= id[r] - 1; ++i) res += dp[i][l - 1];
    68         }
    69         printf("%d
    ", res);
    70         lastans = res;
    71     }
    72      
    73     return 0;
    74 } 
    View Code
  • 相关阅读:
    谈屡面屡胜的面试经验
    同步异步和阻塞非阻塞的区别
    Ansible条件测试
    Ansible playbook基础组件介绍
    Ansible的基础元素和YAML介绍
    Ansible常见模块介绍
    Ansible介绍及安装部署
    Spark介绍及安装部署
    安装部署Apache Hadoop (完全分布式模式并且实现NameNode HA和ResourceManager HA)
    安装部署Apache Hadoop (本地模式和伪分布式)
  • 原文地址:https://www.cnblogs.com/vb4896/p/6971481.html
Copyright © 2020-2023  润新知