Bzoj 3809: Gty的二逼妹子序列 莫队,分块
3809: Gty的二逼妹子序列
Time Limit: 35 Sec Memory Limit: 28 MBSubmit: 868 Solved: 234
[Submit][Status][Discuss]
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
HINT
样例的部分解释:
5 9 1 2
子序列为4 1 5 1 2
在[1,2]里的权值有1,1,2,有2种,因此答案为2。
3 4 7 9
子序列为5 1
在[7,9]里的权值有5,有1种,因此答案为1。
4 4 2 5
子序列为1
没有权值在[2,5]中的,因此答案为0。
2 3 4 7
子序列为4 5
权值在[4,7]中的有4,5,因此答案为2。
建议使用输入/输出优化。
Source
题解:
直接莫队加分块。(将颜色进行分块即可)
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 100010 4 #define MAXM 1000010 5 struct node 6 { 7 int l,r,a,b,id; 8 }q[MAXM]; 9 int tot[MAXN],sum[336],pos[MAXN],C[MAXN],block,ans[MAXM]; 10 int read() 11 { 12 int s=0,fh=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 15 return s*fh; 16 } 17 bool cmp(node aa,node bb) 18 { 19 if(pos[aa.l]==pos[bb.l])return aa.r<bb.r; 20 return aa.l<bb.l; 21 } 22 void Del(int color)//删除一种颜色 23 { 24 tot[color]--;//该种颜色个数-1. 25 if(tot[color]==0)sum[(color-1)/block+1]--;//以前有的颜色,现在没有了.(个数从1变为0.) 26 } 27 void Add(int color)//加上一种颜色 28 { 29 tot[color]++;//该种颜色个数+1. 30 if(tot[color]==1)sum[(color-1)/block+1]++;//以前没有的颜色,现在有了.(个数从0变为1.) 31 } 32 int getans(int aa,int bb) 33 { 34 int gs=0,left=(aa-1)/block+1,right=(bb-1)/block+1,i; 35 if(left==right) 36 { 37 for(i=aa;i<=bb;i++)if(tot[i]!=0)gs++; 38 return gs; 39 } 40 for(i=aa;i<=left*block;i++)if(tot[i]!=0)gs++; 41 for(i=left+1;i<=right-1;i++)gs+=sum[i]; 42 for(i=(right-1)*block+1;i<=bb;i++)if(tot[i]!=0)gs++; 43 return gs; 44 } 45 int main() 46 { 47 int n,m,i,L,R; 48 n=read();m=read(); 49 for(i=1;i<=n;i++)C[i]=read(); 50 for(i=1;i<=m;i++) 51 { 52 q[i].l=read();q[i].r=read();q[i].a=read();q[i].b=read(); 53 q[i].id=i; 54 } 55 block=(int)sqrt(n); 56 for(i=1;i<=n;i++)pos[i]=(i-1)/block+1; 57 sort(q+1,q+m+1,cmp); 58 memset(sum,0,sizeof(sum));//每一块内的颜色个数. 59 memset(tot,0,sizeof(tot));//枚举的区间内的每种颜色的个数. 60 L=1;R=0; 61 for(i=1;i<=m;i++) 62 { 63 while(L<q[i].l) 64 { 65 Del(C[L]); 66 L++; 67 } 68 while(L>q[i].l) 69 { 70 L--; 71 Add(C[L]); 72 } 73 while(R<q[i].r) 74 { 75 R++; 76 Add(C[R]); 77 } 78 while(R>q[i].r) 79 { 80 Del(C[R]); 81 R--; 82 } 83 ans[q[i].id]=getans(q[i].a,q[i].b); 84 } 85 for(i=1;i<=m;i++)printf("%d\n",ans[i]); 86 fclose(stdin); 87 fclose(stdout); 88 return 0; 89 }