Bzoj3236: [Ahoi2013]作业

Bzoj3236: [Ahoi2013]作业

刚学完莫队,不过这题用莫队的复杂度算起来好高啊,居然能过……

像求逆序对一样用两个树状数组维护区间中每个数值出现的个数,以及每个数是否出现,前者用来求答案1,后者用来求答案2。

在区间伸缩时加入删除最后更新答案即可。

这次压行压的有点厉害,和DeepinC有的一拼了……

 

 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 }
完整代码

 

波澜前,面不惊。
posted @ 2019-07-25 06:11  Al_Ca  阅读(132)  评论(2编辑  收藏  举报
ヾ(≧O≦)〃嗷~