题目大意:给定一个序列,多次询问[l,r]区间内[a,b]范围内的数有多少
内存28MB,树套树可以歇菜了
首先普通的莫队+树状数组应该都能想到 这样做每次增加/删除一个点是O(logn)的 查询也是O(logn) 时间复杂度O(m√nlogn) 过(bu)不(hao)去(ka)
考虑将树状数组 改成分块 这样虽然查询变成了O(√n) 但是修改变成了O(1)的
这样就把时间复杂度降到了O(m√n) 常数写小点亲测能卡过去
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
struct query{
int l,r,a,b,_id;
bool operator < (const query &x) const;
}queries[1001001];
int n,m,block,l=1,r=0;
int a[M],belong[M],ans[1001001];
int cnt[M],block_cnt[330];
bool query :: operator < (const query &x) const
{
if( belong[l] != belong[x.l] )
return l < x.l;
return r < x.r;
}
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 int Get_Int()
{
char c;
int 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();
return re;
}
}
class OStream{
private:
static const int L=1<<15;
char stack[20];int top;
char buffer[L],*S;
public:
OStream()
{
S=buffer;
}
void Put_Int(int x)
{
stack[++top]='\n';
if(!x) stack[++top]='0';
else while(x)
stack[++top]=x%10+'0',x/=10;
while(top)
{
if(S==buffer+L-1)
{
printf("%s",buffer);
S=buffer;
}
*S++=stack[top--];
}
}
~OStream()
{
*S=0;
puts(buffer);
}
}os;
inline void Update(int x)
{
cnt[x]++;
if(cnt[x]==1)
block_cnt[belong[x]]++;
}
inline void Downdate(int x)
{
cnt[x]--;
if(cnt[x]==0)
block_cnt[belong[x]]--;
}
int Query(int x,int y)
{
int i,re=0;
if(belong[y]-belong[x]<=1)
{
for(i=x;i<=y;i++)
re+=(bool)cnt[i];
return re;
}
for(i=belong[x]+1;i<belong[y];i++)
re+=block_cnt[i];
for(i=x;i<=belong[x]*block;i++)
re+=(bool)cnt[i];
for(i=y;i>=(belong[y]-1)*block+1;i--)
re+=(bool)cnt[i];
return re;
}
int main()
{
int i;
cin>>n>>m;
if(n<=10)
block=(int)sqrt(n);
else
block=(int)sqrt(n);
for(i=1;i<=n;i++)
{
a[i]=IStream::Get_Int();
belong[i]=(i-1)/block+1;
}
for(i=1;i<=m;i++)
{
queries[i].l=IStream::Get_Int();
queries[i].r=IStream::Get_Int();
queries[i].a=IStream::Get_Int();
queries[i].b=IStream::Get_Int();
queries[i]._id=i;
}
sort(queries+1,queries+m+1);
for(i=1;i<=m;i++)
{
while(r<queries[i].r)
Update(a[++r]);
while(l>queries[i].l)
Update(a[--l]);
while(r>queries[i].r)
Downdate(a[r--]);
while(l<queries[i].l)
Downdate(a[l++]);
ans[queries[i]._id]=Query(queries[i].a,queries[i].b);
}
for(i=1;i<=m;i++)
os.Put_Int(ans[i]);
return 0;
}