1188 - Fast Queries
PDF (English) Statistics Forum
Time Limit: 3 second(s) Memory Limit: 64 MB
Given an array of N integers indexed from 1 toN, and q queries, each in the form i j, you have to findthe number of distinct integers from index i to j (inclusive).
Input
Input starts with an integer T (≤ 5),denoting the number of test cases.
The first line of a case is a blank line. The next linecontains two integers N (1 ≤ N ≤ 105), q (1≤ q ≤ 50000). The next line contains N space separatedintegers forming the array. There integers range in [0, 105].
Each of the next q lines will contain a query whichis in the form i j (1 ≤ i ≤ j ≤ N).
Output
For each test case, print the case number in a single line.Then for each query you have to print a line containing number of distinctintegers from index i to j.
Sample Input
Output for Sample Input
1
8 5
1 1 1 2 3 5 1 2
1 8
2 3
3 6
4 5
4 8
Case 1:
4
1
4
2
4
Note
Dataset is huge. Use faster I/O methods.
题意:n个数,m个区间,找区间不同数的个数
题解: 裸的莫队分块,时间复杂度近似为q*(n^1.5).
#include<cstdio>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<functional>
#include<cstring>
#include<string>
#include<cstdlib>
#include<iomanip>
#include<numeric>
#include<cctype>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
using namespace std;
const int maxn=1000005;
typedef long long ll;
int n,m,k;
//莫队算法主要处理离线问题,查询只给出L,R
//当[L,R]很容易向[L-1,R],[L+1,R],[L,R-1],[L,R+1]转移时可用莫队
//注意转移的时候先扩张再收缩,L先向右,L再向左,最后再收缩
//add就是当前区间添加某元素时要做的操作
//del就是当前区间删除某元素时要做的操作
//add,del函数写的时候都要注意结构顺序
struct node
{
int l,r,id;
}Q[maxn]; ///保存询问值
int pos[maxn];///保存所在块
bool cmp(const node &a,const node &b)///先按l所在块的大小排,在按r的位置排
{
return pos[a.l]<pos[b.l]||(pos[a.l]==pos[b.l]&&(pos[a.l]&1?a.r<b.r:a.r>b.r));///奇偶排序
}
ll gcd_(ll a,ll b)
{
return b==0?a:gcd_(b,a%b);
}
int num[maxn*2];
int a[maxn];
ll ans[maxn],ans2[maxn];
int L=0,R=0;
ll Ans=0;
void add(int x)
{
num[a[x]]++;
if(num[a[x]]==1) Ans++;
}
void del(int x)
{
num[a[x]]--;
if(num[a[x]]==0) Ans--;
}
int main()
{ int T;
scanf("%d",&T);
int cas=0;
while(T--)
{
memset(num,0,sizeof(num));
cas++;
scanf("%d%d",&n,&m);
int sz=n/sqrt(m*2/3);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pos[i]=i/sz;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&Q[i].l,&Q[i].r);
Q[i].id=i;
}
sort(Q+1,Q+1+m,cmp);
num[0]=0;
L=1;R=0;Ans=0;
for(int i=1;i<=m;i++)
{
while(R<Q[i].r)
{
R++;
add(R);
}
while(L>Q[i].l) ///前缀和L+1>Q[i].l
{
L--;
add(L);
}
while(L<Q[i].l)///前缀和L+1<Q[i].l
{
del(L);
L++;
}
while(R>Q[i].r)
{
del(R);
R--;
}
ans[Q[i].id]=Ans;
}
printf("Case %d:\n",cas);
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
}
return 0;
}