洛谷 P1972 [SDOI2009]HH的项链【莫队算法学习】

P1972 [SDOI2009]HH的项链

题目背景

题目描述

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

输入输出格式

输入格式:

第一行:一个整数N,表示项链的长度。

第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间的整数)。

第三行:一个整数M,表示HH 询问的个数。

接下来M 行:每行两个整数,L 和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

输出格式:

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

输入输出样例

输入样例#1:
6
1 2 3 4 3 5
3
1 2
3 5
2 6
输出样例#1:
2
2
4

说明

数据范围:

对于100%的数据,N <= 50000,M <= 200000。

题目链接:https://www.luogu.org/problem/show?pid=1972

分析:莫队算法经典题,算是模版题吧!学习一下!

下面给出AC代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1001010;
  4 typedef long long ll;
  5 int n,m,unit;
  6 inline int read()
  7 {
  8     int x=0,f=1;
  9     char ch=getchar();
 10     while(ch<'0'||ch>'9')
 11     {
 12         if(ch=='-')
 13             f=-1;
 14         ch=getchar();
 15     }
 16     while(ch>='0'&&ch<='9')
 17     {
 18         x=x*10+ch-'0';
 19         ch=getchar();
 20     }
 21     return x*f;
 22 }
 23 inline void write(int x)
 24 {
 25     if(x<0)
 26     {
 27         putchar('-');
 28         x=-x;
 29     }
 30     if(x>9)
 31     {
 32         write(x/10);
 33     }
 34     putchar(x%10+'0');
 35 }
 36 struct Query
 37 {
 38     int L,R,id;
 39 }node[maxn];
 40 ll gcd(ll a,ll b)///求最大公约数
 41 {
 42     return b==0?a:gcd(b,a%b);
 43 }
 44 struct Ans
 45 {
 46     ll a,b;
 47     void reduce()///分数简化操作
 48     {
 49         ll d=gcd(a,b);
 50         a/=d;
 51         b/=d;
 52     }
 53 }ans[maxn];
 54 bool cmp(Query a,Query b)///把1~n分成sqrt(n)段,unit=sqrt(n)m个查询先按照第几个块排序,再按照R排序,分块处理
 55 {
 56     if(a.L/unit!=b.L/unit)
 57         return a.L/unit<b.L/unit;
 58     else return a.R<b.R;
 59 }
 60 int a[maxn];
 61 int num[maxn];
 62 inline void work()
 63 {
 64     ll temp=0;
 65     memset(num,false,sizeof(num));
 66     int L=1;
 67     int R=0;
 68     for(int i=0;i<m;i++)///莫队算法核心部分
 69     {
 70         while(R<node[i].R)
 71         {
 72             R++;
 73             ///temp-=(ll)num[a[R]]*num[a[R]];
 74             ///num[a[R]]++;
 75             ///temp+=(ll)num[a[R]]*num[a[R]];
 76             if(!num[a[R]])
 77                 temp++;
 78             num[a[R]]++;
 79         }
 80         while(R>node[i].R)
 81         {
 82             ///temp-=(ll)num[a[R]]*num[a[R]];
 83             num[a[R]]--;
 84             ///temp+=(ll)num[a[R]]*num[a[R]];
 85             ///R--;
 86             if(!num[a[R]])
 87                 temp--;
 88             R--;
 89         }
 90         while(L<node[i].L)
 91         {
 92             ///temp-=(ll)num[a[L]]*num[a[L]];
 93             num[a[L]]--;
 94             ///temp+=(ll)num[a[L]]*num[a[L]];
 95             ///L++;
 96             if(!num[a[L]])
 97                 temp--;
 98             L++;
 99         }
100         while(L>node[i].L)
101         {
102             L--;
103             ///temp-=(ll)num[a[L]]*num[a[L]];
104             ///num[a[L]]++;
105             ///temp+=(ll)num[a[L]]*num[a[L]];
106             if(!num[a[L]])
107                 temp++;
108             num[a[L]]++;
109         }
110         ans[node[i].id].a=temp;
111         ///ans[node[i].id].b=(ll)(R-L+1)*(R-L);
112         ///ans[node[i].id].reduce();
113     }
114 }
115 int main()
116 {
117     n=read();
118     for(int i=1;i<=n;i++)
119         a[i]=read();
120     m=read();
121     for(int i=0;i<m;i++)
122     {
123         node[i].id=i;
124         node[i].L=read();
125         node[i].R=read();
126     }
127     unit=(int)sqrt(n);
128     sort(node,node+m,cmp);
129     work();
130     for(int i=0;i<m;i++)
131         printf("%lld\n",ans[i].a);
132     return 0;
133 }

 

posted @ 2017-07-04 15:58  Angel_Kitty  阅读(455)  评论(0编辑  收藏  举报