题目
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]的权值的种类数。
分析
要么写树套树,可是只有28M的空间,所以莫队吧。
莫队+树状数组很好想,但是这样就是O(n^1.5logn)。
有个很厉害的思路就是用分块把修改变成O(1),查询变成O(n^0.5)
这样最终时间复杂度就是O(n*1.5)
卡一卡就能过去
这里的优化思路可以这么分析:
用树状数组则修改O(n*n^0.5*logn),查询O(n*(n^0.5+logn)),所以想个办法再综合一下,分块刚刚好嘛
orzPoPoQQQ大爷的加速输入
顺便,由于分块没有初始化,然后TLE了3次,每次卡80S,卡住了不少人,对不起大家QAQ。
代码
注意:
1、分块的初始化操作即使不做也不会错,但是会T很惨
2、莫队注意修改的时候++i和i++不同情况不一样。
#include<cmath>
#include<queue>
#include<cctype>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+105,maxm=1e6+105;
namespace IStream{
const int L=1<<15;
char buffer[L],*S,*T;
inline char Get_Char()
{
if(S==T)
{
T=(S=buffer)+fread(buffer,1,L,stdin);
if(S==T) return EOF;
}
return *S++;
}
inline void Rd(int &re)
{
char c;
re=0;
for(c=Get_Char();(c<'0'||c>'9');c=Get_Char());
while(c>='0'&&c<='9')
re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();
}
int tt[20],sz;
inline void Pt(int x)
{
sz=0;
do{
tt[++sz]=x%10;
x/=10;
}while(x);
for(int i=sz;i;i--)putchar(tt[i]^48);
putchar('\n');
}
}
int n,m;
int co[maxn],belong[maxn];
struct block{
static const int TIM=320;
int num,vis[maxn],d[maxn/TIM+5],L[maxn/TIM+5],R[maxn/TIM+5];
void Build()
{
L[0]=R[0]=0;
for(num=1;num*TIM<n;num++)
{
L[num]=R[num-1]+1,R[num]=L[num]+TIM-1;
for(int i=L[num];i<=R[num];i++)belong[i]=num;
}
L[num]=R[num-1]+1,R[num]=n;
for(int i=L[num];i<=R[num];i++)belong[i]=num;
}
void add(int v)
{
if(!vis[v])d[belong[v]]++;
vis[v]++;
}
void del(int v)
{
if(vis[v]==1)d[belong[v]]--;
vis[v]--;
}
int query(int l,int r)
{
int ret=0;
if(belong[l]==belong[r])
{
for(int i=l;i<=r;i++)if(vis[i])ret++;
return ret;
}
for(int i=l;i<=R[belong[l]];i++)if(vis[i])ret++;
for(int i=belong[l]+1;R[i]<r;i++)ret+=d[i];
for(int i=L[belong[r]];i<=r;i++)if(vis[i])ret++;
return ret;
}
}blo;
namespace modui
{
int ans[maxm];
struct data{
int l,r,a,b,id;
friend bool operator<(data a,data b)
{
return belong[a.l]!=belong[b.l]?belong[a.l]<belong[b.l]:a.r<b.r;
}
}q[maxm];
void Init()
{
IStream::Rd(n);IStream::Rd(m);
blo.Build();
for(int i=1;i<=n;i++)IStream::Rd(co[i]);
for(int i=1;i<=m;i++)
{
q[i].id=i;
IStream::Rd(q[i].l);
IStream::Rd(q[i].r);
IStream::Rd(q[i].a);
IStream::Rd(q[i].b);
}
sort(q+1,q+m+1);
}
void modui()
{
int L=1,R=0;
for(int i=1;i<=m;i++)
{
while(L<q[i].l)blo.del(co[L++]);
while(L>q[i].l)blo.add(co[--L]);
while(R<q[i].r)blo.add(co[++R]);
while(R>q[i].r)blo.del(co[R--]);
ans[q[i].id]=blo.query(q[i].a,q[i].b);
}
}
void work()
{
Init();
modui();
for(int i=1;i<=m;i++)
IStream::Pt(ans[i]);
}
}
int main()
{
modui::work();
return 0;
}