Bzoj3809--Gty的二逼妹子序列
一开始想到是树套树,空间28m树套树就狗带了
这题可以用莫队去做,如果在莫队下跑的是树状数组或者线段树的话复杂度要多带个log,可能跑不过
所以换成是分块。为什么分块,因为分块可以o(1)修改。
这里分块是针对值域来分而不是下标,外面套个莫队时间复杂度m*sqrt(n)+n*sqrt(n)
代码:
#include<bits/stdc++.h> using namespace std; #define MAXN 100005 #define MAXM 1000006 int ret;char c; inline int read() { ret=0;c=getchar(); while(c>'9'||c<'0') c=getchar(); while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar(); return ret; } int s[MAXN],ans[MAXM],n,m,qsz; struct que{ int l,r,a,b,id; }q[MAXM]; int bl[MAXN],cnt[MAXN],blk[MAXN]; bool cmp(que a,que b) {return bl[a.l]==bl[b.l]?a.r<b.r:a.l<b.l;} inline void Up(int x) {cnt[x]++;if(cnt[x]==1) blk[bl[x]]++;} inline void Down(int x) {cnt[x]--;if(cnt[x]==0) blk[bl[x]]--;} int Query(int l,int r) { int ret=0; if(bl[l]==bl[r]) { for(int i=l;i<=r;i++) ret+=(bool)cnt[i]; return ret; } for(int i=bl[l]+1;i<bl[r];i++) ret+=blk[i]; for(int i=(bl[l]+1)*qsz-1;i>=l;i--) ret+=(bool)cnt[i]; for(int i=bl[r]*qsz;i<=r;i++) ret+=(bool)cnt[i]; return ret; } int main() { n=read();m=read(); qsz=(int)sqrt(n); for(int i=1;i<=n;i++) s[i]=read(); for(int i=1;i<=n;i++) bl[i]=i/qsz; for(int i=1;i<=m;i++) { q[i].l=read();q[i].r=read(); q[i].a=read();q[i].b=read(); q[i].id=i; } sort(q+1,q+m+1,cmp); int l=1,r=0; for(int i=1;i<=m;i++) { while(r<q[i].r) Up(s[++r]); while(l>q[i].l) Up(s[--l]); while(r>q[i].r) Down(s[r--]); while(l<q[i].l) Down(s[l++]); ans[q[i].id]=Query(q[i].a,q[i].b); } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }