3343: 教主的魔法

来源:互联网 发布:python proxyfix 编辑:程序博客网 时间:2024/04/26 06:02

题目链接

题目大意:维护数列,资磁区间加,询问区间内大于等于C的数的个数

题解:分块
将原数组复制一份副本,维护其单调性
修改:同一块/不完整块直接加,整块打标记,重构不完整块(块内不一定单调)
查询:同一块/不完整块暴力,整块二分
初始化要重构所有块
O(Qnlogn)

我的收获:分块T1达成

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>using namespace std;const int M=1000005;#define opes for(int i=l;i<=r;i++)#define opel for(int i=l;i<=min(pos[l]*blo,r);i++)#define oper for(int i=(pos[r]-1)*blo+1;i<=r;i++)#define opea for(int i=pos[l]+1;i<=pos[r]-1;i++)int n,q,m,blo,tot;int a[M],b[M],pos[M],add[M];void reset(int x){    int l=(x-1)*blo+1,r=min(x*blo,n);//找块的左右端点     opes b[i]=a[i];    sort(b+l,b+r+1);//左闭右开 }int find(int x,int v){    int l=(x-1)*blo+1,r=min(x*blo,n);    int ans=lower_bound(b+l,b+r+1,v)-b;//找到大于等于v的第一个数     return r-ans+1;//右端点-左端点=区间长度 }void update(int l,int r,int v){    if(pos[l]==pos[r]) opes a[i]+=v;    else    {        opel a[i]+=v;        oper a[i]+=v;        opea add[i]+=v;        reset(pos[l]);reset(pos[r]);    }}int query(int l,int r,int v){    int ret=0;    if(pos[l]==pos[r]) opes ret+=a[i]+add[pos[i]]>=v;    else    {        opel ret+=a[i]+add[pos[i]]>=v;        oper ret+=a[i]+add[pos[i]]>=v;        opea ret+=find(i,v-add[i]);    }    return ret;}void work(){    char opt[5];    int x,y,z;    while(m--){        scanf("%s%d%d%d",opt,&x,&y,&z);        if(opt[0]=='M') update(x,y,z);        if(opt[0]=='A') printf("%d\n",query(x,y,z));    }}void init(){    cin>>n>>m;blo=sqrt(n);tot=(n-1)/blo+1;    for(int i=1;i<=n;i++)        scanf("%d",&a[i]),pos[i]=(i-1)/blo+1,b[i]=a[i];    for(int i=1;i<=tot;i++) reset(i);}int main(){    init();    work();    return 0;}
原创粉丝点击