Bzoj3236: [Ahoi2013]作业
刚学完莫队,不过这题用莫队的复杂度算起来好高啊,居然能过……
像求逆序对一样用两个树状数组维护区间中每个数值出现的个数,以及每个数是否出现,前者用来求答案1,后者用来求答案2。
在区间伸缩时加入删除最后更新答案即可。
这次压行压的有点厉害,和DeepinC有的一拼了……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 using namespace std; 6 int L[1010],R[1010],pos[100010]; 7 struct ques 8 { 9 int L,R,a,b,id; 10 #define L(x) que[x].L 11 #define R(x) que[x].R 12 #define a(x) que[x].a 13 #define b(x) que[x].b 14 #define id(x) que[x].id 15 friend bool operator < (ques a,ques b) 16 { 17 return (pos[a.L]^pos[b.L])?(pos[a.L]<pos[b.L]):((pos[a.L]&1)?(a.R<b.R):(a.R>b.R)); 18 } 19 }que[1000010]; 20 int C[100010],C2[100010],cnt[100010]; 21 int n,m,a[100010]; 22 int eans1[1000010],eans2[1000010]; 23 #define lowbit(x) ((x)&(-(x))) 24 inline int read() 25 { 26 int s=0;char a=getchar(); 27 while(a<'0'||a>'9')a=getchar(); 28 while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} 29 return s; 30 } 31 void add(int x,int y) 32 {while(x<=100010){C[x]+=y;x+=lowbit(x);}} 33 int ask(int x) 34 {int ans=0;while(x){ans+=C[x];x-=lowbit(x);}return ans;} 35 void add2(int x,int y) 36 {while(x<=100010){C2[x]+=y;x+=lowbit(x);}} 37 int ask2(int x) 38 {int ans=0;while(x){ans+=C2[x];x-=lowbit(x);}return ans;} 39 signed main() 40 { 41 cin>>n>>m; 42 for(int i=1;i<=n;i++)a[i]=read(); 43 for(int i=1;i<=m;i++) 44 L(i)=read(),R(i)=read(),a(i)=read(),b(i)=read(),id(i)=i; 45 int t=sqrt(n); 46 for(int i=1;i<=t;i++) 47 L[i]=R[i-1]+1,R[i]=i*t; 48 if(R[t]<n)t++,L[t]=R[t-1]+1;R[t]=n; 49 for(int i=1;i<=t;i++) 50 for(int j=L[i];j<=R[i];j++) 51 pos[j]=i; 52 sort(que+1,que+m+1); 53 int l=1,r=0,ans1=0,ans2=0; 54 for(int i=1;i<=m;i++) 55 { 56 ans1=ask(b(i))-ask(a(i)-1); 57 while(l>L(i)){l--,add(a[l],1),ans1=ask(b(i))-ask(a(i)-1);if(cnt[a[l]]==0)add2(a[l],1);cnt[a[l]]++; } 58 while(l<L(i)){add(a[l],-1),ans1=ask(b(i))-ask(a(i)-1);if(cnt[a[l]]==1)add2(a[l],-1);cnt[a[l]]--,l++;} 59 while(r<R(i)){r++,add(a[r],1),ans1=ask(b(i))-ask(a(i)-1);if(cnt[a[r]]==0)add2(a[r],1);cnt[a[r]]++; } 60 while(r>R(i)){add(a[r],-1),ans1=ask(b(i))-ask(a(i)-1);if(cnt[a[r]]==1)add2(a[r],-1);cnt[a[r]]--,r--;} 61 ans2=ask2(b(i))-ask2(a(i)-1); 62 eans1[id(i)]=ans1,eans2[id(i)]=ans2; 63 } 64 for(int i=1;i<=m;i++) 65 printf("%d %d\n",eans1[i],eans2[i]); 66 }
波澜前,面不惊。