【BZOJ 3809】 3809: Gty的二逼妹子序列 (莫队+分块)
3809: Gty的二逼妹子序列
Time Limit: 80 Sec Memory Limit: 28 MB
Submit: 1728 Solved: 513Description
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
Sample Output
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
【分析】
一开始打莫队+树状数组,好尴尬80s T了卡评测。。
然后因为树状数组logn修改 logn查询。
这里分块就比较优越的(其实跟我之前看的块状链表没什么区别吧?),分块做的话是单点修改O(1),询问$\sqrt n$的。
对于莫队这种单点改来改去的题目就很好了。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 #define Maxn 100010 9 #define Maxm 1000010 10 11 int mymin(int x,int y) {return x<y?x:y;} 12 13 int s[Maxn],sm[Maxn],bl[Maxn]; 14 int sq,n,m; 15 16 struct node {int x,y,a,b,id,ans;}t[Maxm]; 17 bool cmp(node x,node y) {return (x.x/sq==y.x/sq)?(x.y<y.y):(x.x<y.x);} 18 bool cmp2(node x,node y) {return x.id<y.id;} 19 20 int c[Maxn],rt[Maxn]; 21 22 int query(int x,int y) 23 { 24 int L=bl[x],R=bl[y]; 25 int ans=0; 26 for(int i=L+1;i<R;i++) ans+=c[i]; 27 if(L==R) 28 { 29 for(int i=x;i<=y;i++) ans+=(sm[i]>=1?1:0); 30 } 31 else 32 { 33 for(int i=x;i<=rt[L];i++) ans+=(sm[i]>=1?1:0); 34 for(int i=rt[R-1]+1;i<=y;i++) ans+=(sm[i]>=1?1:0); 35 } 36 return ans; 37 } 38 39 int main() 40 { 41 scanf("%d%d",&n,&m); 42 for(int i=1;i<=n;i++) scanf("%d",&s[i]); 43 for(int i=1;i<=n;i++) sm[i]=0; 44 for(int i=1;i<=m;i++) 45 { 46 scanf("%d%d%d%d",&t[i].x,&t[i].y,&t[i].a,&t[i].b); 47 t[i].id=i; 48 } 49 sq=(int)ceil(sqrt((double)n)); 50 sort(t+1,t+1+m,cmp); 51 for(int i=1;i<=n;i++) bl[i]=i/sq+1; 52 for(int i=1;i<=sq;i++) rt[i]=mymin(sq*i-1,n); 53 for(int i=1;i<=sq;i++) c[i]=0; 54 int l=1,r=0; 55 for(int i=1;i<=m;i++) 56 { 57 while(r<t[i].y) 58 { 59 if(sm[s[r+1]]==0) c[bl[s[r+1]]]++; 60 sm[s[r+1]]++; 61 r++; 62 } 63 while(l>t[i].x) 64 { 65 if(sm[s[l-1]]==0) c[bl[s[l-1]]]++; 66 sm[s[l-1]]++; 67 l--; 68 } 69 while(l<t[i].x) 70 { 71 if(sm[s[l]]==1) c[bl[s[l]]]--; 72 sm[s[l]]--; 73 l++; 74 } 75 while(r>t[i].y) 76 { 77 if(sm[s[r]]==1) c[bl[s[r]]]--; 78 sm[s[r]]--; 79 r--; 80 } 81 t[i].ans=query(t[i].a,t[i].b); 82 } 83 sort(t+1,t+1+m,cmp2); 84 for(int i=1;i<=m;i++) printf("%d\n",t[i].ans); 85 return 0; 86 }
2017-03-26 15:23:10