# bzoj 3236: 洛谷 P4396: [AHOI2013]作业 (莫队, 分块)

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define F(i,a,b) for(int i=(a);i<=(b);++i)
4
5 int n,q,S,T,U;
6 int a[100001],b[100001],blk[100001];
7 struct D{int l,r,a,b,id;}Q[100001];
8 bool cmp(D i,D j){return blk[i.l]==blk[j.l]?i.r<j.r:blk[i.l]<blk[j.l];}
9 int cnt[100001],bel[100001],sum[320],num[320];
10 pair<int,int> Ans[100001];
11
12 void Ins(int p,int x){
13     if(!cnt[p]) ++num[bel[p]];
14     cnt[p]+=x, sum[bel[p]]+=x;
15     if(!cnt[p]) --num[bel[p]];
16 }
17
18 pair<int,int> Qur(int a,int b){
19     if(a>b) return make_pair(0,0);
20     int S=0,N=0;
21     if(bel[a]==bel[b]) F(i,a,b) {if(cnt[i]) S+=cnt[i], ++N;}
22     else{
23         F(i,bel[a]+1,bel[b]-1) S+=sum[i], N+=num[i];
24         F(i,a,bel[a]*U) if(cnt[i]) S+=cnt[i], ++N;
25         F(i,bel[b]*U-U+1,b) if(cnt[i]) S+=cnt[i], ++N;
26     }
27     return make_pair(S,N);
28 }
29
30 int main(){
31     scanf("%d%d",&n,&q); S=sqrt(n)+0.5;
32     F(i,1,n) blk[i]=(i-1)/S+1;
33     F(i,1,n) scanf("%d",a+i), b[i]=a[i];
34     sort(b+1,b+n+1); T=unique(b+1,b+n+1)-b-1;
35     U=sqrt(T)+0.5;
36     F(i,1,T) bel[i]=(i-1)/U+1;
37     F(i,1,n) a[i]=lower_bound(b+1,b+T+1,a[i])-b;
38     F(i,1,q) scanf("%d%d%d%d",&Q[i].l,&Q[i].r,&Q[i].a,&Q[i].b), Q[i].id=i;
39     sort(Q+1,Q+q+1,cmp);
40     int L=1,R=0;
41     F(i,1,q){
42         while(L>Q[i].l) --L, Ins(a[L],1);
43         while(R<Q[i].r) ++R, Ins(a[R],1);
44         while(L<Q[i].l) Ins(a[L],-1), ++L;
45         while(R>Q[i].r) Ins(a[R],-1), --R;
46         Ans[Q[i].id]=Qur(lower_bound(b+1,b+T+1,Q[i].a)-b,upper_bound(b+1,b+T+1,Q[i].b)-b-1);
47     }
48     F(i,1,q) printf("%d %d\n",Ans[i].first,Ans[i].second);
49     return 0;
50 }

posted @ 2018-09-03 23:56  粉兔  阅读(215)  评论(0编辑  收藏  举报