Description
Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题。
对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数。
为了方便,我们规定妹子们的美丽度全都在[1,n]中。
给定一个长度为n(1<=n<=100000)的正整数序列s(1<=si<=n),对于m(1<=m<=1000000)次询问“l,r,a,b”,每次输出sl...sr中,权值∈[a,b]的权值的种类数。
Input
第一行包括两个整数n,m(1<=n<=100000,1<=m<=1000000),表示数列s中的元素数和询问数。
第二行包括n个整数s1...sn(1<=si<=n)。
接下来m行,每行包括4个整数l,r,a,b(1<=l<=r<=n,1<=a<=b<=n),意义见题目描述。
保证涉及的所有数在C++的int内。
保证输入合法。
Output
对每个询问,单独输出一行,表示sl...sr中权值∈[a,b]的权值的种类数。
Sample Input
10 10
4 4 5 1 4 1 5 1 2 1
5 9 1 2
3 4 7 9
4 4 2 5
2 3 4 7
5 10 4 4
3 9 1 1
1 4 5 9
8 9 3 3
2 2 1 6
8 9 1 4
4 4 5 1 4 1 5 1 2 1
5 9 1 2
3 4 7 9
4 4 2 5
2 3 4 7
5 10 4 4
3 9 1 1
1 4 5 9
8 9 3 3
2 2 1 6
8 9 1 4
Sample Output
2
0
0
2
1
1
1
0
1
2
0
0
2
1
1
1
0
1
2
题意概述:给出一个序列,每次询问问序列区间[L,R]中的元素里权值在[a,b]中的不同元素种类数。
总的一句话:所有可以用O(1)时间(总之就是代价很小)把区间[l,r]的询问转化到区间[l+1,r],[l,r-1]的询问的可离线问题都可以用莫队干掉!
观察这个问题,可以发现如果你维护一个维护元素的数据结构,那么显然可以在你移动区间左右指针的时候做到快速修改答案,这正符合了莫队算法的用途。
使用分块来做这个维护元素的数据结构,因为它支持O(1)修改啊!每一次查询的时候时间复杂度和移动指针的时间代价是几乎相同的。
时间复杂度O((2N+M)*sqrt(N))
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<set> 9 #include<map> 10 #include<vector> 11 #include<cctype> 12 using namespace std; 13 const int MAXN=100005; 14 const int MAXQ=1000005; 15 const int size=205; 16 17 int N,M,S[MAXN],ans[MAXQ]; 18 struct que{ 19 int id,l,r,a,b; 20 friend bool operator < (que a,que b){ 21 return a.l/size<b.l/size||a.l/size==b.l/size&&a.r<b.r; 22 } 23 }q[MAXQ]; 24 struct BLOCK{ 25 static const int maxn=100005; 26 static const int SIZE=500; 27 static const int maxm=205; 28 int c[maxn],kind[maxm],lef[maxm],rig[maxm],cnt,belong[maxn]; 29 BLOCK(){ cnt=1; } 30 void build(int n){ 31 int p=1; 32 while(p+SIZE<n+1){ 33 lef[cnt]=p,rig[cnt]=p+SIZE,p+=SIZE,cnt++; 34 for(int i=lef[cnt-1];i<rig[cnt-1];i++) belong[i]=cnt-1; 35 } 36 lef[cnt]=p,rig[cnt]=n+1; 37 for(int i=lef[cnt];i<rig[cnt];i++) belong[i]=cnt; 38 } 39 void update(int p,int v){ 40 if(c[p]&&c[p]+v==0) kind[belong[p]]--; 41 if(!c[p]&&c[p]+v==1) kind[belong[p]]++; 42 c[p]+=v; 43 } 44 int query(int L,int R){ 45 int re=0,p=L; 46 if(belong[L]==belong[R]){ 47 for(int i=L;i<=R;i++) if(c[i]) re++; 48 return re; 49 } 50 for(int i=L;i<rig[belong[L]];i++) if(c[i]) re++; 51 for(int i=lef[belong[R]];i<=R;i++) if(c[i]) re++; 52 for(int i=belong[L]+1;i<belong[R];i++) re+=kind[i]; 53 return re; 54 } 55 }block; 56 57 void _scanf(int &x) 58 { 59 x=0; 60 char c=getchar(); 61 while(c<'0'||c>'9') c=getchar(); 62 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 63 } 64 int out_cnt,out[15]; 65 void _printf(int x) 66 { 67 out[++out_cnt]=x%10,x/=10; 68 while(x) out[++out_cnt]=x%10,x/=10; 69 while(out_cnt) putchar('0'+out[out_cnt--]); 70 putchar('\n'); 71 } 72 void data_in() 73 { 74 _scanf(N);_scanf(M); 75 for(int i=1;i<=N;i++) _scanf(S[i]); 76 for(int i=1;i<=M;i++){ 77 _scanf(q[i].l);_scanf(q[i].r); 78 _scanf(q[i].a);_scanf(q[i].b); 79 q[i].id=i; 80 } 81 } 82 void movep(int &i,int j,int t) 83 { 84 while(i<j){ 85 if(!t) block.update(S[i++],-1); 86 else block.update(S[++i],1); 87 } 88 while(i>j){ 89 if(!t) block.update(S[--i],1); 90 else block.update(S[i--],-1); 91 } 92 } 93 void work() 94 { 95 sort(q+1,q+M+1); 96 block.build(N); 97 int l=1,r=1; 98 block.update(S[1],1); 99 for(int i=1;i<=M;i++){ 100 movep(r,q[i].r,1); 101 movep(l,q[i].l,0); 102 ans[q[i].id]=block.query(q[i].a,q[i].b); 103 } 104 for(int i=1;i<=M;i++) _printf(ans[i]); 105 } 106 int main() 107 { 108 data_in(); 109 work(); 110 return 0; 111 }