bzoj3343: 教主的魔法

来源:互联网 发布:医疗优化站不收录 编辑:程序博客网 时间:2024/03/29 17:28

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3343

思路:分块大法好...

分块,每块内部保持有序。

修改时,给完整的块打标记,两段不完整的暴力改

询问时,给完整的块二分查找,两段不完整的暴力查。

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>const int maxn=1000010,maxk=2010;using namespace std;int n,m,q;char op[5],ch;struct Block{int a[maxn],b[maxn],add[maxk],pos[maxn],sz;void clear(int x){int l=(x-1)*sz+1,r=min(x*sz,n);for (int i=l;i<=r;i++) b[i]=a[i];sort(b+l,b+r+1);}void change(int x,int y,int v){if (pos[x]==pos[y]) for (int i=x;i<=y;i++) a[i]+=v;else{for (int i=x;i<=pos[x]*sz;i++) a[i]+=v;for (int i=(pos[y]-1)*sz+1;i<=y;i++) a[i]+=v;}clear(pos[x]),clear(pos[y]);for (int i=pos[x]+1;i<pos[y];i++) add[i]+=v; }int find(int x,int v){int l=(x-1)*sz+1,r=min(x*sz,n),mid=(l+r)>>1,cnt=r;while (l<=r){if (b[mid]>=v) r=mid-1;else l=mid+1;mid=(l+r)>>1;}return cnt-l+1;}int query(int x,int y,int v){int sum=0;if (pos[x]==pos[y]) for (int i=x;i<=y;i++) sum+=(a[i]+add[pos[i]]>=v);else{for (int i=x;i<=pos[x]*sz;i++) sum+=(a[i]+add[pos[i]]>=v);for (int i=(pos[y]-1)*sz+1;i<=y;i++) sum+=(a[i]+add[pos[i]]>=v);}for (int i=pos[x]+1;i<pos[y];i++) sum+=find(i,v-add[i]);return sum;}}T;void read(int &x){for (ch=getchar();!isdigit(ch);ch=getchar());for (x=0;isdigit(ch);ch=getchar()) x=x*10+ch-'0';}int main(){scanf("%d%d",&n,&q);T.sz=(int)sqrt(n);for (int i=1;i<=n;i++){read(T.a[i]),T.pos[i]=(i-1)/T.sz+1;}m=n/T.sz+(n%T.sz?1:0);for (int i=1;i<=m;i++) T.clear(i);for (int i=1,x,y,z;i<=q;i++){scanf("%s",op);read(x),read(y),read(z);if (op[0]=='M') T.change(x,y,z);else printf("%d\n",T.query(x,y,z)); }return 0;}


0 0