【bzoj3809】Gty的二逼妹子序列

【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\n",q[i].ans);

97 } 

posted on 2015-09-06 01:41  forgot93  阅读(237)  评论(0编辑  收藏  举报

导航