【bzoj3809】Gty的二逼妹子序列
2014年12月21日1,03512
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
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。
建议使用输入/输出优化。
之前一直以为莫对就是分块,
然后这道分块和莫对结合,让我看出两种不同:莫对是用分块去做,但是是对离线询问的一种优化,
得到答案的过程还是要自己的转移路线的。
这一我们对颜色分块,询问一个区间颜色的种类的话,就是O(sqrt(n))了,然后又M次询问,询问时O(sqrt(n)),莫对是n^1.5;
所以复杂度是O((M+N)*sqr(n);
1 #include<iostream>
2 #include<stdio.h>
3 #include<string.h>
4 #include<math.h>
5 #include<algorithm>
6 #include<queue>
7 #include<vector>
8 #include<stdlib.h>
9
10 #define inf 0x3f3f3f
11 #define N 1234567
12
13 using namespace std;
14
15 int a[N],pos[N],block,b[N];
16 int n,m,k;
17 int f[N];
18 struct node
19 {
20 int l,r,id,ans,a,b;
21 }q[N];
22
23 int cmp(node a,node b)
24 {
25 if (pos[a.l]==pos[b.l]) return a.r<b.r;
26 return pos[a.l]<pos[b.l];
27 }
28
29
30 int cmpid(node a,node b)
31 {
32 return a.id<b.id;
33 }
34 int cn[N],B[N];
35 void add(int c,int val)
36 {
37 if (!cn[c]) ++B[pos[c]];
38 cn[c]+=val;
39 if (!cn[c]) --B[pos[c]];
40 }
41
42 int query(int x,int y)
43 {
44 int ans=0;
45 if (pos[x]==pos[y]){
46 for(int i=x;i<=y;i++)
47 if (cn[i]) ans++;
48 }
49 else
50 {
51 for (int i=pos[x]*block;i>=x;i--)
52 if (cn[i]) ans++;
53 for (int i=(pos[y]-1)*block+1;i<=y;i++)
54 if (cn[i]) ans++;
55 for (int i=pos[x]+1;i<pos[y];i++)
56 ans+=B[i];
57 }
58 return ans;
59 }
60 void solve()
61 {
62 int l=1,r=0;
63 int ans=0;
64 for (int i=1;i<=m;i++)
65 {
66 while (l<q[i].l)
67 add(a[l],-1),l++;//减去a[l]产生的影响
68 while (l>q[i].l)
69 l--,add(a[l],1);//加上a[l]的infection
70 while (r>q[i].r)
71 add(a[r],-1),r--;//d the infection of a[r] ,note r-l
72 while (r<q[i].r)
73 r++,add(a[r],1);//add the infection of a[r]
74
75 q[i].ans=query(q[i].a,q[i].b);
76 }
77 }
78
79 int main()
80 {
81 scanf("%d%d",&n,&m);
82 for (int i=1;i<=n;i++) scanf("%d",&a[i]);
83
84 block=sqrt(n);
85
86 for (int i=1;i<=n;i++)
87 pos[i]=(i-1)/block+1;
88
89 for (int i=1;i<=m;i++)
90 scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].a,&q[i].b),q[i].id=i;
91
92 sort(q+1,q+m+1,cmp);
93 solve();
94 sort(q+1,q+m+1,cmpid);
95 for (int i=1;i<=m;i++)
96 printf("%d ",q[i].ans);
2 #include<stdio.h>
3 #include<string.h>
4 #include<math.h>
5 #include<algorithm>
6 #include<queue>
7 #include<vector>
8 #include<stdlib.h>
9
10 #define inf 0x3f3f3f
11 #define N 1234567
12
13 using namespace std;
14
15 int a[N],pos[N],block,b[N];
16 int n,m,k;
17 int f[N];
18 struct node
19 {
20 int l,r,id,ans,a,b;
21 }q[N];
22
23 int cmp(node a,node b)
24 {
25 if (pos[a.l]==pos[b.l]) return a.r<b.r;
26 return pos[a.l]<pos[b.l];
27 }
28
29
30 int cmpid(node a,node b)
31 {
32 return a.id<b.id;
33 }
34 int cn[N],B[N];
35 void add(int c,int val)
36 {
37 if (!cn[c]) ++B[pos[c]];
38 cn[c]+=val;
39 if (!cn[c]) --B[pos[c]];
40 }
41
42 int query(int x,int y)
43 {
44 int ans=0;
45 if (pos[x]==pos[y]){
46 for(int i=x;i<=y;i++)
47 if (cn[i]) ans++;
48 }
49 else
50 {
51 for (int i=pos[x]*block;i>=x;i--)
52 if (cn[i]) ans++;
53 for (int i=(pos[y]-1)*block+1;i<=y;i++)
54 if (cn[i]) ans++;
55 for (int i=pos[x]+1;i<pos[y];i++)
56 ans+=B[i];
57 }
58 return ans;
59 }
60 void solve()
61 {
62 int l=1,r=0;
63 int ans=0;
64 for (int i=1;i<=m;i++)
65 {
66 while (l<q[i].l)
67 add(a[l],-1),l++;//减去a[l]产生的影响
68 while (l>q[i].l)
69 l--,add(a[l],1);//加上a[l]的infection
70 while (r>q[i].r)
71 add(a[r],-1),r--;//d the infection of a[r] ,note r-l
72 while (r<q[i].r)
73 r++,add(a[r],1);//add the infection of a[r]
74
75 q[i].ans=query(q[i].a,q[i].b);
76 }
77 }
78
79 int main()
80 {
81 scanf("%d%d",&n,&m);
82 for (int i=1;i<=n;i++) scanf("%d",&a[i]);
83
84 block=sqrt(n);
85
86 for (int i=1;i<=n;i++)
87 pos[i]=(i-1)/block+1;
88
89 for (int i=1;i<=m;i++)
90 scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].a,&q[i].b),q[i].id=i;
91
92 sort(q+1,q+m+1,cmp);
93 solve();
94 sort(q+1,q+m+1,cmpid);
95 for (int i=1;i<=m;i++)
96 printf("%d ",q[i].ans);
97 }