「BZOJ3343」教主的魔法(分块+二分查找)

题意:

给定一个数列,您需要支持以下两种操作:
给[l,r]同加一个数
询问[l,r]中有多少数字大于或等于v

(n<=1000000,m<=3000)

题解

块内排序二分查询
修改就用个数组存整块的修改值
不完整的部分都暴力修改和查询
时间复杂度大概O(Qsqrt(n)logn)

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=1001000; 
 8 int n,m,a[N],b[N],block[N],L[2000],R[2000],cnt[2000],ans,Block;
 9 int find(int x,int y){
10     int l=L[x];int r=R[x];
11     int tmp=9999999;
12     while(l<=r){
13         int mid=(l+r)>>1;
14         if(b[mid]>=y){
15             tmp=mid;
16             r=mid-1;
17         }
18         else l=mid+1;
19     }
20     return max(0,R[x]-tmp+1);
21 }
22 int main(){
23     scanf("%d%d",&n,&m);
24     Block=sqrt(n);
25     for(int i=1;i<=n;i++){
26         scanf("%d",&a[i]);
27         b[i]=a[i];
28         block[i]=(i-1)/Block+1;
29         if(!L[block[i]])L[block[i]]=i;
30         R[block[i]]=i;
31     }
32     for(int i=1;i<=block[n];i++){
33         sort(b+L[i],b+1+R[i]);
34     }
35     char s[10];
36     while(m--){
37         scanf("%s",s);
38         if(s[0]=='A'){
39             int l,r,c;
40             ans=0;
41             scanf("%d%d%d",&l,&r,&c);
42             for(int i=l;i<=R[block[l]];i++)
43                 if(a[i]>=c)ans++;
44             for(int i=L[block[r]];i<=r;i++)
45                 if(a[i]>=c)ans++;
46             if(block[l]+1<block[r])
47                 for(int i=block[l]+1;i<=block[r]-1;i++){
48                     ans+=find(i,c-cnt[i]);
49                 }
50             printf("%d\n",ans);
51         }
52         else{
53             int l,r,c;
54             scanf("%d%d%d",&l,&r,&c);
55             if(block[l]+1<block[r])
56                 for(int i=block[l]+1;i<=block[r]-1;i++)
57                     cnt[i]+=c;
58             for(int i=l;i<=R[block[l]];i++)
59                 a[i]+=c;
60             for(int i=L[block[l]];i<=R[block[l]];i++)
61                 b[i]=a[i];
62             sort(b+L[block[l]],b+1+R[block[l]]);
63             for(int i=L[block[r]];i<=r;i++)
64                 a[i]+=c;
65             for(int i=L[block[r]];i<=R[block[r]];i++)
66                 b[i]=a[i];
67             sort(b+L[block[r]],b+1+R[block[r]]);
68         }
69     }
70     return 0;
71 }

猜你喜欢

转载自www.cnblogs.com/Xu-daxia/p/9480534.html