bzoj3236 作业 莫队+树状数组
莫队+树状数组
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #define N 100055 #define M 1000066 using namespace std; int gy[N],be[N],c[M],cc[M],n,m,nn,maxn,tot,num[N]; struct Query{ int l,r,a,b,id,ans1,ans2; }qr[M]; bool cmp1(Query a,Query b){ if(be[a.l]==be[b.l]) return a.r<b.r; return be[a.l]<be[b.l]; } bool cmp2(Query a,Query b){ return a.id<b.id; } int lowbit(int x){ return x&(-x); } void add(int x,int y){ int xx=x; if(y==1&&++num[xx]==1){ while(xx<=maxn){ cc[xx]++; xx+=lowbit(xx); } } if(y==-1&&--num[xx]==0){ while(xx<=maxn){ cc[xx]--; xx+=lowbit(xx); } } while(x<=maxn){ c[x]+=y; x+=lowbit(x); } } int query(int x){ if(x>maxn) x=maxn; int ans=0; while(x){ ans+=c[x]; x-=lowbit(x); } return ans; } int query1(int x){ if(x>maxn) x=maxn; int ans=0; while(x){ ans+=cc[x]; x-=lowbit(x); } return ans; } void work(){ int l=1,r=0;tot=0; for(int i=1;i<=m;i++){ while(l<qr[i].l) add(gy[l++],-1); while(l>qr[i].l) add(gy[--l],1); while(r<qr[i].r) add(gy[++r],1); while(r>qr[i].r) add(gy[r--],-1); qr[i].ans1=query(qr[i].b)-query(qr[i].a-1); qr[i].ans2=query1(qr[i].b)-query1(qr[i].a-1); } } int main() { scanf("%d%d",&n,&m); nn=(int)sqrt(n); for(int i=1;i<=n;i++){ scanf("%d",&gy[i]); be[i]=(i-1)/nn+1; maxn=max(maxn,gy[i]); } int l,r,a,b; for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&l,&r,&a,&b); qr[i].l=l; qr[i].r=r; qr[i].a=a; qr[i].b=b; qr[i].id=i; } sort(qr+1,qr+m+1,cmp1); work(); sort(qr+1,qr+m+1,cmp2); for(int i=1;i<=m;i++) printf("%d %d\n",qr[i].ans1,qr[i].ans2); return 0; }
人生如梦亦如幻 朝如晨露暮如霞。