[BZOJ 3236][Ahoi2013]作业(莫队+树状数组)
Description
Solution
莫队
一开始维护数的个数和数值的个数都用了树状数组,果断超时QAQ
把数的个数改成了按权值分块
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define N 100005 #define M 1000005 using namespace std; int n,m,block,x[N],pos[N],ans1[M],ans2[M],num[N]; int g1[N]; struct Node { int l,r,a,b,id; bool operator < (const Node& t) const { if(pos[l]==pos[t.l]) return pos[r]<pos[t.r]; else return pos[l]<pos[t.l]; } }q[M]; struct BIT { int c[N]; inline int lowbit(int x){return x&-x;} void add(int pos,int x) { while(pos<=n) c[pos]+=x,pos+=lowbit(pos); } int query(int pos) { int res=0; while(pos>0)res+=c[pos],pos-=lowbit(pos); return res; } }t2; int read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void change(int t,int f) { g1[pos[x[t]]]+=f;//t1.add(x[t],f); if(num[x[t]]==0&&f==1)t2.add(x[t],1); else if(num[x[t]]==1&&f==-1)t2.add(x[t],-1); num[x[t]]+=f; } void query(int id,int a,int b) { if(pos[a]==pos[b]) { for(int i=a;i<=b;i++) ans1[id]+=num[i]; return; } for(int i=a;i<=pos[a]*block;i++)ans1[id]+=num[i]; for(int i=pos[a]+1;i<=pos[b]-1;i++)ans1[id]+=g1[i]; for(int i=b;i>(pos[b]-1)*block;i--)ans1[id]+=num[i]; } int main() { n=read(),m=read(); block=(int)sqrt(n); for(int i=1;i<=n;i++) x[i]=read(),pos[i]=(i-1)/block+1; 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+1+m); int l=1,r=0; for(int i=1;i<=m;i++) { while(l<q[i].l)change(l++,-1); while(l>q[i].l)change(--l,1); while(r>q[i].r)change(r--,-1); while(r<q[i].r)change(++r,1); if(q[i].a<0)q[i].a=1; query(q[i].id,q[i].a,q[i].b); ans2[q[i].id]=t2.query(q[i].b)-t2.query(q[i].a-1); } for(int i=1;i<=m;i++) printf("%d %d\n",ans1[i],ans2[i]); return 0; }