3809: Gty的二逼妹子序列
Time Limit: 35 Sec Memory Limit: 28 MB
Submit: 878 Solved: 238
[Submit][Status][Discuss]
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。
* 题解*
1.询问无修改—-》莫队,排序处理询问(O(logn+sqrt(n)*n));
2.首先很容易想出 树状数组GET(b)-GET(a-1) 出区间答案。。
3.分块优化,按区间答案分块;
代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#define maxm 1000015
#define maxn 100015
int n,m;
using namespace std;
struct node{
int x,y,a,b;
int id;
}q[maxm];
int ans[maxm];
int nn;
int aa[maxn]; //aa[i]是 i点的值;
int bb[maxn]; //bb[i]是i出现的次数
int cnt[10005]; //分块
int be[maxn]; //值所在的belong
int cmp(node xx,node yy)
{
if(be[xx.x]!=be[yy.x]) return xx.x<yy.x;
else return xx.y<yy.y;
}
int cal(int x,int y)
{
int an=0;
int X=be[x];
int Y=be[y];
for(int i=X+1;i<=Y-1;i++) an+=cnt[i];
if(X!=Y)
{
while(be[x]==X)
{
if(bb[x]>0) an++;
x++;
}
while(be[y]==Y)
{
if(bb[y]>0) an++;
y--;
}
}
else
{
for(int i=x;i<=y;i++)
if(bb[i]) an++;
}
return an;
}
void solve()
{
int now=0;
int lx=0,rx=0;
for(int i=1;i<=m;i++)
{
int ll=q[i].x;
int rr=q[i].y;
while(lx<ll)
{
bb[aa[lx]]--;
if(bb[aa[lx]]==0) cnt[be[aa[lx]]]--;
lx++;
}
while(rx>rr)
{
bb[aa[rx]]--;
if(bb[aa[rx]]==0) cnt[be[aa[rx]]]--;
rx--;
}
while(lx>ll)
{
lx--;
bb[aa[lx]]++;
if(bb[aa[lx]]==1) cnt[be[aa[lx]]]++;
}
while(rx<rr)
{
rx++;
bb[aa[rx]]++;
if(bb[aa[rx]]==1) cnt[be[aa[rx]]]++;
}
ans[q[i].id]=cal(q[i].a,q[i].b);
}
}
int main()
{
scanf("%d%d",&n,&m);
nn=sqrt(n);
for(int i=1;i<=n;i++) be[i]=(i-1)/nn+1;
for(int i=1;i<=n;i++) scanf("%d",&aa[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&q[i].x,&q[i].y,&q[i].a,&q[i].b);
q[i].id=i;
}
sort(q+1,q+1+m,cmp);
solve();
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}