bzoj 3809: Gty的二逼妹子序列
3809: Gty的二逼妹子序列
Time Limit: 80 Sec Memory Limit: 28 MBDescription
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。
建议使用输入/输出优化。
Solution:
这里对于数字进行分块,然后我们将询问根据左端点排序后,就可以用莫队在很可观的的时间复杂度内算出答案了
本蒟蒻打出的第一个莫队(+分块),how amazing. 算法的魅力阿 以及就是不写读入优化,你咬我呀
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int maxn=100020; 8 const int maxm=1000020; 9 struct haha 10 { 11 int l,r,a,b,pos; 12 }q[maxm]; 13 int a[maxn],ans[maxm],bel[maxn],c[maxn],sum[maxn],n,m; 14 bool cmp(const haha lu,const haha d) {return bel[lu.l] == bel[d.l] ? lu.r < d.r : lu.l < d.l;} 15 void inti() 16 { 17 scanf("%d%d",&n,&m); 18 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 19 for(int i=1;i<=m;i++) scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].a,&q[i].b),q[i].pos=i; 20 int block; 21 block=sqrt(n+0.5); 22 for(int i=1;i<=n;i++) bel[i]=(i-1)/block+1; 23 } 24 int query(int a,int b) 25 { 26 int l=bel[a],r=bel[b],tot=0; 27 if(l==r) 28 { 29 for(int i=a;i<=b;i++) 30 if(c[i]>0) tot++; 31 return tot; 32 } 33 for(int i=a;bel[i]==bel[a];i++) 34 if(c[i]>0) tot++; 35 for(int i=b;bel[i]==bel[b];i--) 36 if(c[i]>0) tot++; 37 for(int i=bel[a]+1;i<bel[b];i++) 38 tot+=sum[i]; 39 return tot; 40 } 41 void updata(int x,int flag) 42 { 43 c[x]+=flag; 44 if(flag==-1&&c[x]==0) sum[bel[x]]--; 45 if(flag==1&&c[x]==1) sum[bel[x]]++; 46 } 47 void work() 48 { 49 sort(q+1,q+m+1,cmp); 50 int l,r,ll,rr; l=1;r=0; 51 for(int i=1;i<=m;i++) 52 { 53 ll=q[i].l;rr=q[i].r; 54 while(l<ll) updata(a[l++],-1); 55 while(l>ll) updata(a[--l],1); 56 while(r<rr) updata(a[++r],1); 57 while(r>rr) updata(a[r--],-1); 58 ans[q[i].pos]=query(q[i].a,q[i].b); 59 } 60 } 61 int main() 62 { 63 inti(); 64 work(); 65 for(int i=1;i<=m;i++) 66 printf("%d\n",ans[i]); 67 return 0; 68 }