• 牛客网多校训练第一场 J


    链接:

    https://www.nowcoder.com/acm/contest/139/J

    题意:

    给出n个整数的序列a(1≤ai≤n)和q个询问(1≤n,q≤1e5),每个询问包含两个整数L和R(1≤L,R≤n)。
    对于每个询问,输出a[1...L]和a[R...n]的不同数字的个数。

    分析:

    将原数组复制一份拼接到末尾,把询问a[1...L]和a[R...n]转换为询问a[R...L+n]。
    设kind[i]为a[1...i]出现的数字种类,
    则询问a[L...R]的答案为 kind[R] - kind[L-1] +(a[1...L-1]和a[L...R]同时出现的数字种类)。
    可以用树状数组维护a[1...L-1]和a[L...R]同时出现的数字种类。
    如果a[i]在区间1...L-1出现过,则对应的树状数组位置的值应为1。查询时只需查询区间L...R。
    可以对询问区间按左端点排序,左端点每次右移时把对应的数的下一个位置在树状数组里加1即可。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int MAXS = 1e6 + 5;
     7 int sf[MAXS];
     8 void add(int p, int v, int n) {
     9     while(p <= n) sf[p] += v, p += p&-p;
    10 }
    11 int sum(int p) {
    12     int res = 0;
    13     while(p) res += sf[p], p -= p&-p;
    14     return res;
    15 }
    16 
    17 struct REGION {
    18     int L, R, id;
    19     bool operator < (const REGION& that) const {
    20         return L < that.L;
    21     }
    22 } r[MAXS];
    23 int a[MAXS], kind[MAXS], nxt[MAXS], rec[MAXS], ans[MAXS];
    24 
    25 int main() {
    26     int n, q;
    27     while(~scanf("%d%d", &n, &q)) {
    28         for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    29         for(int i = 0; i < q; i++) {
    30             scanf("%d%d", &r[i].R, &r[i].L);
    31             r[i].R += n;
    32             r[i].id = i;
    33         }
    34         memcpy(a+n+1, a+1, n*sizeof(int));
    35         n *= 2;
    36         memset(rec, false, sizeof(rec));
    37         for(int i = 1; i <= n; i++) {
    38             if(rec[a[i]]) kind[i] = kind[i-1];
    39             else kind[i] = kind[i-1] + 1, rec[a[i]] = true;
    40         }
    41         memset(rec, false, sizeof(rec));
    42         for(int i = n; i > 0; i--) {
    43             nxt[i] = rec[a[i]];
    44             rec[a[i]] = i;
    45         }
    46         sort(r, r + q);
    47         memset(sf, 0, sizeof(sf));
    48         for(int p = 1, i = 0; i < q; i++) {
    49             while(p < r[i].L) add(nxt[p], 1, n), p++;
    50             ans[r[i].id] = kind[r[i].R]-kind[r[i].L-1] + sum(r[i].R)-sum(r[i].L-1);
    51         }
    52         for(int i = 0; i < q; i++) printf("%d
    ", ans[i]);
    53     }
    54     return 0;
    55 }
  • 相关阅读:
    智能家居测试思路
    Linux中,&和&&,|和||
    Eclipse设置保存代码时自动格式化代码
    Eclipse常用快捷键
    Eclipse设置快捷出现函数
    Eclipse设置代码背景色
    PDF转换成Word后乱码怎么办?
    Able2Extract快捷键汇总整理
    安装并激活Parallels Desktop商业版
    想在Mac上使用CAD?
  • 原文地址:https://www.cnblogs.com/hkxy125/p/9446976.html
Copyright © 2020-2023  润新知