您的位置:首页 > 其它

分块二分——BZO3343 教主的魔法

2017-12-12 15:54 120 查看
题面:BZOJ3343

分块二分大暴力!

以前初三刚学分块的时候以为这题很难QAQ,现在认为……

这题实在是water到不知道哪里去了666

我们对于数据分块,然后对块内的数进行排序

修改的时候发现如果整个块都被覆盖在区间里面的话,那么就对整个块进行标记(因为整个块内的数都被加上了)

两边多出来的暴力修改,然后再次对块内进行排序

排序的原因是询问时要对块进行二分

询问还是老办法,对于一整个块的数据我们二分找比要求的数大的个数(这就是排序的原因),对于多出来的暴力统计

时间复杂度大约是O(Qn√∗logn)

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <ctime>
#include <map>
#include <queue>
#include <cstdlib>
#include <string>
#include <climits>
#include <set>
#include <vector>
using namespace std;
inline int read(){
int k=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();}
return k*f;
}
inline void write(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);putchar(x%10+'0');
}
inline void writeln(int x){
write(x);puts("");
}
int n,m,c,p,a[1000001],w[1000001]={0},b[1000001]={0},sum[1000001]={0};
inline void yu(int x){
int l=(x-1)*p+1,r=min(n,x*p);
for(int i=l;i<=r;i++)b[i]=a[i];
sort(b+l,b+r+1);
}
inline void add(int x,int y,int z){
if(w[x]==w[y])for(int i=x;i<=y;i++)a[i]+=z;
else{
for(int i=x;i<=w[x]*p;i++)a[i]+=z;
for(int i=(w[y]-1)*p+1;i<=y;i++)a[i]+=z;
}
yu(w[x]);yu(w[y]);
for(int i=w[x]+1;i<w[y];i++)sum[i]+=z;
}
inline int erfen(int x,int v){
int l=(x-1)*p+1,r=min(n,x*p);int la=r;
while(l<=r){
int mm=(l+r)/2;
if(b[mm]<v)l=mm+1;
else r=mm-1;
}
return la-l+1;
}
inline int ssum(int x,int y,int z){
int ans=0;
if(w[x]==w[y]){for(int i=x;i<=y;i++)if(a[i]+sum[w[i]]>=z)ans++;}
else{
for(int i=x;i<=w[x]*p;i++)if(a[i]+sum[w[i]]>=z)ans++;
for(int i=(w[y]-1)*p+1;i<=y;i++)if(a[i]+sum[w[i]]>=z)ans++;
}
for(int i=w[x]+1;i<w[y];i++)ans+=erfen(i,z-sum[i]);
return ans;
}
int main()
{
n=read();c=read();
p=(int)(sqrt(n));
for(<
d801
span class="hljs-keyword">int i=1;i<=n;i++){
a[i]=read();
w[i]=(i-1)/p+1;
b[i]=a[i];
}
if(n%p==0)m=n/p;
else m=n/p+1;
for(int i=1;i<=m;i++)yu(i);
for(int i=1;i<=c;i++){
char ss[5];scanf("%s",ss);int x=read(),y=read(),z=read();
if(ss[0]=='M')add(x,y,z);
else writeln(ssum(x,y,z));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  分块 二分 暴力