题目大意:给定一个序列,多次询问[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; }