• [SDOI 2009]HH的项链


    Description

    HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝 壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此,他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。

    Input

    第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

    Output

    M行,每行一个整数,依次表示询问对应的答案。

    Sample Input

    6
    1 2 3 4 3 5
    3
    1 2
    3 5
    2 6

    Sample Output

    2
    2
    4

    HINT

    对于20%的数据,N ≤ 100,M ≤ 1000;
    对于40%的数据,N ≤ 3000,M ≤ 200000;
    对于100%的数据,N ≤ 50000,M ≤ 200000。

    题解

    这题首先在线是没法做的,所以我们可以考虑离线算法

    解法1:莫队裸题,分块就好。

     1 #include<map>
     2 #include<queue>
     3 #include<stack>
     4 #include<cmath>
     5 #include<ctime>
     6 #include<cstdio>
     7 #include<string>
     8 #include<vector>
     9 #include<cstdlib>
    10 #include<cstring>
    11 #include<iostream>
    12 #include<algorithm>
    13 #define LL long long
    14 #define RE register
    15 #define IL inline
    16 using namespace std;
    17 const int M=1000000;
    18 const int N=50000;
    19 const int Q=200000;
    20 
    21 int cnt[M+5],ans;
    22 int keep[Q+5];
    23 int n,m,a[N+5],tim;
    24 struct query
    25 {
    26     int l,r,id;
    27 }q[Q+5];
    28 bool comp(const query &a,const query &b){return a.l/tim==b.l/tim ? a.r<b.r:a.l<b.l;}
    29 
    30 int main()
    31 {
    32     scanf("%d",&n);
    33     tim=sqrt(n);
    34     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    35     scanf("%d",&m);
    36     for (int i=1;i<=m;i++)
    37     {
    38         scanf("%d%d",&q[i].l,&q[i].r);
    39         q[i].id=i;
    40     }
    41     sort(q+1,q+m+1,comp);
    42     int curl=0,curr=0,l,r;
    43     for (int i=1;i<=m;i++)
    44     {
    45         l=q[i].l,r=q[i].r;
    46         while (curl<l) {cnt[a[curl]]--;ans-=(cnt[a[curl++]]==0);}
    47         while (curl>l) {cnt[a[--curl]]++;ans+=(cnt[a[curl]]==1);}
    48         while (curr<r) {cnt[a[++curr]]++;ans+=(cnt[a[curr]]==1);}
    49         while (curr>r) {cnt[a[curr]]--;ans-=(cnt[a[curr--]]==0);}
    50         keep[q[i].id]=ans;
    51     }
    52     for (int i=1;i<=m;i++) printf("%d
    ",keep[i]);
    53     return 0;
    54 }
    莫队

    解法2:排序+树状数组。

    首先记录下每种颜色的下一种颜色所在的位置,将所有询问按照右端点进行排序。

    左往右扫,扫过一个元素将该位置++,若有前驱,将前驱--。

    扫到区间端点,答案为$sum[r]-sum[l-1]$,记录一下就好。(其中$sum$为前缀和)

    前缀和用树状数组实现。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 struct Node
     7 {
     8     int l,r,num;
     9 }s[200001];
    10 int a[50001],ans[200001],n,m,c[100001],vis[1000001];
    11 bool cmp(Node a,Node b)
    12 {
    13     return (a.r<b.r||(a.r==b.r&&a.l<b.l));
    14 }
    15 int getsum(int x)
    16 {
    17     int s=0;
    18     while (x)
    19     {
    20         s+=c[x];
    21         x-=(x&(-x));
    22     }
    23     return s;
    24 }
    25 void add(int x,int d)
    26 {
    27     while (x<=n)
    28     {
    29         c[x]+=d;
    30         x+=(x&(-x));
    31     }
    32 }
    33 int main()
    34 {int i,j;
    35     cin>>n;
    36     for (i=1;i<=n;i++)
    37     {
    38         scanf("%d",&a[i]);
    39     }
    40     cin>>m;
    41     for (i=1;i<=m;i++)
    42     {
    43         scanf("%d%d",&s[i].l,&s[i].r);
    44         s[i].num=i;
    45     }
    46     sort(s+1,s+m+1,cmp);
    47     j=1;
    48     for (i=1;i<=n+1;i++)
    49     {
    50         while (j<=m&&i>s[j].r)
    51         {
    52             ans[s[j].num]=getsum(s[j].r)-getsum(s[j].l-1);
    53             j++;
    54         }
    55         if (i>n) break;
    56         if (vis[a[i]])
    57         {
    58             add(vis[a[i]],-1);
    59             vis[a[i]]=i;
    60             add(i,1);
    61         }
    62         else 
    63         {
    64             vis[a[i]]=i;
    65             add(i,1);
    66         }
    67     }
    68     for (i=1;i<=m;i++)
    69     printf("%d
    ",ans[i]);
    70 }
    排序+树状数组
  • 相关阅读:
    Linux 下判断磁盘是ssd还是hdd
    Ceph rgw COR测试
    nfs 挂载选项
    【Linux命令】dmsetup--device mapper 管理工具(更底层的管理工具)
    Device Mapper 存储介绍
    easyui combotree 默认 初始化时就选中
    EasyUI 添加tab页(iframe方式)(转)
    EasyUI DataGrid 配置参数
    EasyUI 后台接受DataGrid传来的参数
    (转)combogrid的代码实例
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7260245.html
Copyright © 2020-2023  润新知