【bzoj3809】Gty的二逼妹子序列
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。
建议使用输入/输出优化。
该题要求什么题目已经说得很清楚了。。。
把这个题再打一遍只不过是想在温习一下莫队算法还记不记得。。。
莫队算法果然是深入OIER的人心啊,感天动地我竟然还会打(不会打莫队真是愧对CJ前辈啊);
这个题的思想很巧妙。。。这题如果用树状数组来实现的话可以实现logn的转移和查询可以获得60分。。。
这个题的巧妙之处就是对值域进行分块!!!
这样的话莫队l和r指针移动时的转移是O(1)的,而每个询问的查询是sqrt(n)的;
查询的话还是用分快查询的常见套路,整块的直接加,不是整块的就暴力搞。。。
而出现次数的话开一个桶就可以实现了,类似HH的项链。。。
一开始l[i]成(i-1)*block了,忘了加1。。。。
附上代码:
1 // MADE BY QT666 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<iostream> 6 #include<queue> 7 #include<set> 8 #include<cstdlib> 9 #include<cstring> 10 #include<string> 11 #include<ctime> 12 #define lson num<<1 13 #define rson num<<1|1 14 using namespace std; 15 typedef long long ll; 16 const int N=100050; 17 const int M=1000050; 18 int gi() 19 { 20 int x=0,flag=1; 21 char ch=getchar(); 22 while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();} 23 while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); 24 return x*flag; 25 } 26 int n,m,a[N],block,pos[N],blockans[N],l[N],r[N],cnt,ans[M],tong[N]; 27 struct ac 28 { 29 int l,r,L,R,id; 30 }q[M]; 31 bool cmp(const ac &a,const ac &b) 32 { 33 if(pos[a.l]==pos[b.l]) return a.r<b.r; 34 return pos[a.l]<pos[b.l]; 35 } 36 void pre() 37 { 38 for(int i=1;i<=cnt;i++) l[i]=(i-1)*block+1,r[i]=i*block; 39 r[cnt]=n; 40 for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1; 41 } 42 void update(int x,int val) {tong[x]+=val;} 43 int query(int x,int y) 44 { 45 int sum=0; 46 if(pos[x]==pos[y]) 47 { 48 for(int i=x;i<=y;i++) if(tong[i]) sum++; 49 } 50 else 51 { 52 for(int i=x;i<=r[pos[x]];i++) if(tong[i]) sum++; 53 for(int i=l[pos[y]];i<=y;i++) if(tong[i]) sum++; 54 for(int i=pos[x]+1;i<=pos[y]-1;i++) sum+=blockans[i]; 55 } 56 return sum; 57 } 58 void work() 59 { 60 for(int i=1,l=1,r=0;i<=m;i++) 61 { 62 while(l>q[i].l) {l--;update(a[l],1);if(tong[a[l]]==1) blockans[pos[a[l]]]++;} 63 while(r<q[i].r) {r++;update(a[r],1);if(tong[a[r]]==1) blockans[pos[a[r]]]++;} 64 while(l<q[i].l) {update(a[l],-1);if(tong[a[l]]==0) blockans[pos[a[l]]]--;l++;} 65 while(r>q[i].r) {update(a[r],-1);if(tong[a[r]]==0) blockans[pos[a[r]]]--;r--;} 66 ans[q[i].id]=query(q[i].L,q[i].R); 67 } 68 } 69 int main() 70 { 71 n=gi(),m=gi(); 72 for(int i=1;i<=n;i++) a[i]=gi(); 73 for(int i=1;i<=m;i++) q[i].l=gi(),q[i].r=gi(),q[i].L=gi(),q[i].R=gi(),q[i].id=i; 74 block=(int)sqrt(n); 75 if(n%block==0) cnt=n/block; 76 else cnt=n/block+1; 77 pre(); 78 sort(q+1,q+1+m,cmp); 79 work(); 80 for(int i=1;i<=m;i++) printf("%d\n",ans[i]); 81 return 0; 82 }