zoukankan      html  css  js  c++  java
  • 牛客网2018多校第一场J题

    链接:https://www.nowcoder.com/acm/contest/139/J
    来源:牛客网

    题目描述

    Given a sequence of integers a1, a2, ..., an and q pairs of integers (l1, r1), (l2, r2), ..., (lq, rq), find count(l1, r1), count(l2, r2), ..., count(lq, rq) where count(i, j) is the number of different integers among a1, a2, ..., ai, aj, aj + 1, ..., an.

    输入描述:

    The input consists of several test cases and is terminated by end-of-file.
    The first line of each test cases contains two integers n and q.
    The second line contains n integers a
    1
    , a
    2
    , ..., a
    n
    .
    The i-th of the following q lines contains two integers l
    i
     and r
    i
    .

    输出描述:

    For each test case, print q integers which denote the result.
    示例1

    输入

    复制
    3 2
    1 2 1
    1 2
    1 3
    4 1
    1 2 3 4
    1 3

    输出

    复制
    2
    1
    3

    备注:

    * 1 ≤ n, q ≤ 10
    5

    * 1 ≤ a
    i
     ≤ n
    * 1 ≤ l
    i
    , r
    i
     ≤ n
    * The number of test cases does not exceed 10.
    参考博客https://www.nowcoder.com/discuss/87249

    作者:scaufat
    链接:https://www.nowcoder.com/discuss/87249
    来源:牛客网

    首先将原数组扩展为2倍长的,即 a[i+n] = a[i]
    对于查询a[1...l]和a[r..n]有多少种不同的数字可以转换为查询 a[r...l+n]有多少种不同的数字
    首先考虑维护一个前缀和,pre[i]表示a[1...i]有多少种不同的数字,那么对于a[l...r]的答案就为pre[r] - pre[l-1] + 在a[l...r]和a[1...l-1]同时出现的数字的种类
    对于如何求在a[l...r]和a[1...l-1]同时出现的数字的种类,可以考虑使用树状数组维护,树状数组的第i个点表示a[i]是否已经在1...l出现过,对于每个查询只需要查树状数组中l~r的区间和即可
    那么我们只要对区间查询进行排序,对于左端每次右移的时候把对应的数的下一个位置加入到数状数组中即可。
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 using namespace std;
      6 const int N = 2e5+10;
      7 int n,m;
      8 int a[N];
      9 int c[N];
     10 int vis[N];
     11 int nex[N]; //记录每个a[i]上一次出现的位置
     12 int last[N];//为了记录nex数组所添加的辅助数组用来记录a[i]上一次出现的位置
     13 int pre[N];
     14 int answer[N];
     15 struct node
     16 {
     17     int l,r,id;
     18 }querys[N];
     19 int cmp(node x,node y)
     20 {
     21     return x.l<y.l;
     22 }
     23 int lowbit(int x)
     24 {
     25     return x&(-x);
     26 }
     27 void update(int id,int val)
     28 {
     29     while(id<=n)
     30     {
     31         c[id]+=val;
     32         id+=lowbit(id);
     33     }
     34 }
     35 int query(int id)
     36 {
     37     int sum = 0;
     38     while(id>0)
     39     {
     40         sum+=c[id];
     41         id-=lowbit(id);
     42     }
     43     return sum;
     44 }
     45 int query(int l,int r)
     46 {
     47     return query(r) - query(l-1);
     48 }
     49 int main()
     50 {
     51     while(scanf("%d%d",&n,&m)!=EOF)
     52     {
     53         memset(last,-1,sizeof(last));
     54         memset(nex,-1,sizeof(nex));
     55         memset(pre,0,sizeof(pre));
     56         memset(vis,0,sizeof(vis));
     57         memset(a,0,sizeof(a));
     58         memset(c,0,sizeof(c));
     59         memset(answer,0,sizeof(answer));
     60         for(int i = 1; i <= n; i++)
     61         {
     62             scanf("%d",&a[i]);
     63             a[i+n] = a[i];
     64         }
     65         n*=2;
     66         pre[0] = 0;
     67         for(int i = 1; i <= n; i++)
     68         {
     69             if(!vis[a[i]])
     70             {
     71                 vis[a[i]] = 1;
     72                 pre[i] = pre[i-1]+1;
     73             }
     74             else{
     75                 pre[i] = pre[i-1];
     76             }
     77             if(~last[a[i]])
     78             {
     79                 nex[last[a[i]]] = i;
     80             }
     81             last[a[i]] = i;
     82         }
     83         for(int i = 0; i < m; i++)
     84         {
     85             scanf("%d%d",&querys[i].l,&querys[i].r);
     86             querys[i].l+=(n/2);
     87             swap(querys[i].l,querys[i].r);
     88             querys[i].id = i;
     89         }
     90         sort(querys,querys+m,cmp);
     91         int now = 1;
     92         for(int i = 0; i < m; i++)
     93         {
     94             while(now < querys[i].l)
     95             {
     96                 if(~nex[now])//如果当前位置的下一个位置存在,就更新树状数组
     97                     update(nex[now],1);//更新当前i位置的数a[i]的下一个下一个位置
     98                 now++;
     99             }
    100             answer[querys[i].id] = pre[querys[i].r]-pre[querys[i].l-1]+query(querys[i].l,querys[i].r);
    101         }
    102         for(int i = 0; i < m; i++)
    103             printf("%d
    ",answer[i]);
    104     }
    105     return 0;
    106 }
  • 相关阅读:
    xutils3批量上传文件
    超详细Android面试的准备与经历分享 | 百度(offer)
    [网站公告]3月10日23:00-4:00阿里云SLB升级,会有4-8次连接闪断团队
    上周热点回顾(3.2-3.8)团队
    发布新博客皮肤red_autumnal_leaves团队
    上周热点回顾(2.23-3.1)团队
    上周热点回顾(2.16-2.22)团队
    上周热点回顾(2.2-2.8)团队
    如何禁止IE自动生成链接团队
    [云上天气预报-有时有闪电]2月3日23:00-4:00阿里云SLB升级期间网络会闪断团队
  • 原文地址:https://www.cnblogs.com/--lr/p/9364917.html
Copyright © 2011-2022 走看看