题目描述
此时己是凌晨两点,刚刚做了Codeforces的小A掏出了英语试卷。英语作业其实不算多,一个小时刚好可以做完。然后是一个小时可以做完的数学作业,接下来是分别都是一个小时可以做完的化学,物理,语文......小A压力巨大。
这是小A碰见了一道非常恶心的数学题,给定了一个长度为n的数列和若干个询问,每个询问是关于数列的区间表示数列的第l个数到第r个数),首先你要统计该区间内大于等于a,小于等于b的数的个数,其次是所有大于等于a,小于等于b的,且在该区间中出现过的数值的个数。
小A望着那数万的数据规模几乎绝望,只能向大神您求救,请您帮帮他吧。
输入输出格式
输入格式:
第一行n,m
接下来n个数表示数列
接下来m行,每行四个数l,r,a,b
输出格式:
输出m行,分别对应每个询问,输出两个数,分别为在l到r这段区间中大小在[a,b]中的数的个数,以及大于等于a,小于等于b的,且在该区间中出现过的数值的个数(具体可以参考样例)。
输入输出样例
输入样例#1: 复制
3 4
1 2 2
1 2 1 3
1 2 1 1
1 3 1 3
2 3 2 3
输出样例#1: 复制
2 2
1 1
3 2
2 1
说明
N<=100000,M<=100000
解题思路:本来是学习线段树在分治上的应用找的练习题,结果跑偏了。。
这个与项链的那个题很像,区间不同数的个数有很多种实现方式。。这个多了一个限制条件就是要求在a,b范围内
这个其实也好办,直接分块。。。。
统计块内数字的个数,和不同数的个数,对于不是完整的块的话直接暴力。。。
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define inf 0x3f3f3f3f
#define LL long long
#define N 200005
#define MAXN 100000
#define inf 0x3f3f3f3f
int B[N],A[N];
struct node
{
int ql,qr,a,b,id;
bool friend operator <(node x,node y)
{
if(B[x.ql]!=B[y.ql])return B[x.ql]<B[y.ql];
else return x.qr<y.qr;
}
}Q[N];
struct node1
{
int a1,a2;
}ou[N];
int len;
int C[N],D[N],E[N];
void add(int x)
{
++C[x];
++D[B[x]];
if(C[x]==1)++E[B[x]];
}
void del(int x)
{
--C[x];
--D[B[x]];
if(C[x]==0)--E[B[x]];
}
void query(int a,int b,int k)
{
for(int i=a;i<=min(b,B[a]*len);i++)
{
if(C[i])ou[k].a1+=C[i],ou[k].a2++;
}
if(B[a]!=B[b])
{
for(int i=(B[b]-1)*len+1;i<=b;i++)
{
if(C[i])ou[k].a1+=C[i],ou[k].a2++;
}
}
rep(i,B[a]+1,B[b]-1)
{
ou[k].a1+=D[i];
ou[k].a2+=E[i];
}
}
void solve(int n,int m)
{
int r=0,l=1;
rep(i,1,m)
{
while(r<Q[i].qr)add(A[++r]);
while(r>Q[i].qr)del(A[r--]);
while(l>Q[i].ql)add(A[--l]);
while(l<Q[i].ql)del(A[l++]);
query(Q[i].a,Q[i].b,Q[i].id);
}
rep(i,1,m)
{
printf("%d %d\n",ou[i].a1,ou[i].a2);
}
}
int main()
{
int n,m;
sca(n),sca(m);
len=sqrt(n);
rep(i,1,n)sca(A[i]);
rep(i,1,n)B[i]=(i-1)/len+1;
rep(i,1,m)
{
scanf("%d%d%d%d",&Q[i].ql,&Q[i].qr,&Q[i].a,&Q[i].b);
Q[i].id=i;
}
sort(Q+1,Q+1+m);
solve(n,m);
}