bzoj3343 分块

来源:互联网 发布:九维网络免费wifi 编辑:程序博客网 时间:2024/05/13 04:33

分成n个块,对于每个块排序,修改时对于整块维护一个增加值的标记.散块暴力维护.对于询问在整块中二分查找,散块暴力比较

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=1000000+10;int a[N],b[N],pos[N],add[N],block,n,m,q;void reset(int x){    int l=(x-1)*block+1,r=min(n,x*block);    fo(i,l,r) b[i]=a[i];    sort(b+l,b+r+1); }void update(int l,int r,int w){    if(pos[l]==pos[r]) {        for(int i=1;i<=r;i++) a[i]+=w;    } else {        for(int i=l;i<=pos[l]*block;i++) a[i]+=w;        for(int i=(pos[r]-1)*block+1;i<=r;i++) a[i]+=w;    }    reset(pos[l]);reset(pos[r]);    for(int i=pos[l]+1;i<=pos[r]-1;i++) add[i]+=w;}int find(int x,int v){    int l=(x-1)*block+1,r=min(block*x,n),    last=r;    while(l<=r) {        int mid=(l+r)>>1;        if(b[mid]<v) l=mid+1;        else r=mid-1;    }    return last-l+1;}int query(int l,int r,int c){    int sum=0;    if(pos[l]==pos[r]) {        for(int i=l;i<=r;i++) if(a[i]+add[pos[i]]>=c) sum++;    }    else {        for(int i=l;i<=pos[l]*block;i++) if(a[i]+add[pos[i]]>=c) sum++;        for(int i=(pos[r]-1)*block+1;i<=r;i++) if(a[i]+add[pos[i]]>=c) sum++;    }    for(int i=pos[l]+1;i<=pos[r]-1;i++) sum+=find(i,c-add[i]);    return sum;} int main(){    scanf("%d%d",&n,&q);    block=int(sqrt(n+0.5));    for(int i=1;i<=n;i++) {        scanf("%d",&a[i]);        pos[i]=(i-1)/block+1;        b[i]=a[i];    }    m=(n-1)/block+1;    fo(i,1,m) reset(i);    for(int l,r,x,i=1;i<=q;i++) {        char op[5];        scanf("%s%d%d%d",op,&l,&r,&x);        if(op[0]=='M') update(l,r,x);        else printf("%d\n",query(l,r,x));    }    return 0;}
原创粉丝点击