bzoj3343: 教主的魔法

来源:互联网 发布:linux修改ip的命令 编辑:程序博客网 时间:2024/05/02 06:03

链接

  http://www.lydsy.com/JudgeOnline/problem.php?id=3809

题解

  这样搞,我们把序列分块,每一块有个标记表示这个块被整体加了几。
  每次查询,对于完整的块,我们提前把里面的元素排好序,每次只要二分一下就好了。
  修改,完整的块,直接打标记即可;对于前后那些零散的,暴力修改之后,把这个块重新拍下序。

代码

//分块#include <cstdio>#include <algorithm>#define maxn 1100000#define maxs 2048using namespace std;int N, Q, a[maxn], tag[maxs], tmp[maxn], size;inline int read(int x=0){    char c=getchar();    while(c<48 or c>57)c=getchar();    while(c>=48 and c<=57)x=(x<<1)+(x<<3)+c-48, c=getchar();    return x;}inline char readc(){    char c=getchar();    while(c^'A' and c^'M')c=getchar();    return c;}inline void init(){    int i, l, r;    N=read(), Q=read();    for(i=1;i<=N;i++)tmp[i]=a[i]=read();    for(size=1;(1<<size)*(1<<size)<=N;size++);size--;    for(i=0;i<=N>>size;i++)    {        l=i<<size, r=(i+1<<size)-1;        sort(tmp+l,tmp+r+1);    }}inline void pushdown(int block){    int l=block<<size, r=(block+1<<size)-1, i;    for(i=l;i<=r;i++)a[i]+=tag[block], tmp[i]+=tag[block];    tag[block]=0;}inline void rebuild(int block){    int l=block<<size, r=(block+1<<size)-1, i;    for(i=l;i<=r;i++)tmp[i]=a[i];    sort(tmp+l,tmp+r+1);}inline void add(int l, int r, int w){    int i;    for(i=(l>>size)+1;i<r>>size;i++)tag[i]+=w;    pushdown(l>>size), pushdown(r>>size);    for(i=l;i>>size==l>>size and i<=r;i++)a[i]+=w;    if((l>>size)^(r>>size))for(i=r;i>>size==r>>size;i--)a[i]+=w;    rebuild(l>>size);if((l>>size)^(r>>size))rebuild(r>>size);}inline int bin(int block, int w){    int l, r, mid;    l=block<<size, r=(block+1<<size)-1;    if(tmp[r]<w)return 0;    while(l^r)    {        mid=(l+r)>>1;        if(tmp[mid]>=w)r=mid;        else l=mid+1;    }    return (block+1<<size)-1 - l + 1;}inline void quiry(int l, int r, int c){    int i, ans=0;    for(i=(l>>size)+1;i<r>>size;i++)ans+=bin(i,c-tag[i]);    pushdown(l>>size), pushdown(r>>size);    for(i=l;i>>size==l>>size and i<=r;i++)if(a[i]>=c)ans++;    if((l>>size)^(r>>size))for(i=r;i>>size==r>>size;i--)if(a[i]>=c)ans++;    printf("%d\n",ans);}int main(){    char type;    int l, r, x;    init();    for(int i=1;i<=Q;i++)    {        type=readc();        l=read(), r=read(), x=read();        if(type=='M')add(l,r,x);        else quiry(l,r,x);    }    return 0;}
0 0
原创粉丝点击