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 }
  • 相关阅读:
    (转)怎样获得与激活Windows 7超级管理员权限
    (转) C代码优化方案
    英语词汇立体记忆 02
    (转)LUA和C之间的函数调用
    通过lua自带例子学习lua 01
    英语词汇立体记忆 01
    反射(类加载内存分析)
    反射(类加载器的作用)
    反射(动态创建对象操作属性)
    反射(分析类初始化)
  • 原文地址:https://www.cnblogs.com/--lr/p/9364917.html
Copyright © 2011-2022 走看看