bzoj千题计划154:bzoj3343: 教主的魔法

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

 

high记录原始身高

HIGH记录每块排序之后的身高

不满一块的直接对high操作,重排之后再赋值给HIGH

块内直接打标记

查询时,不满一块的直接查,一整块的在HIGH内二分块内第一个>=C-标记的点

 

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 1000001

int bl[N];
int high[N],HIGH[N],tmp[N];
int L[1001],R[1001],tag[1001];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

void modify(int l,int r,int w)
{
    if(bl[l]==bl[r])
    {
        for(int i=l;i<=r;++i) high[i]+=w;
        for(int i=L[bl[l]];i<=R[bl[l]];++i) tmp[i]=high[i];
        sort(tmp+L[bl[l]],tmp+R[bl[l]]+1);
        for(int i=L[bl[l]];i<=R[bl[l]];++i) HIGH[i]=tmp[i];
        return;
    }
    for(int i=l;i<=R[bl[l]];++i) high[i]+=w;
    for(int i=L[bl[l]];i<=R[bl[l]];++i) tmp[i]=high[i];
    sort(tmp+L[bl[l]],tmp+R[bl[l]]+1);
    for(int i=L[bl[l]];i<=R[bl[l]];++i) HIGH[i]=tmp[i];
    for(int i=L[bl[r]];i<=r;++i) high[i]+=w;
    for(int i=L[bl[r]];i<=R[bl[r]];++i) tmp[i]=high[i];
    sort(tmp+L[bl[r]],tmp+R[bl[r]]+1);
    for(int i=L[bl[r]];i<=R[bl[r]];++i) HIGH[i]=tmp[i];
    for(int i=bl[l]+1;i<bl[r];++i) tag[i]+=w;
}

int find(int x,int y,int w)
{
    int l=x,r=y,mid,ok=y+1;
    while(l<=r)
    {
        mid=l+r>>1;
        if(HIGH[mid]>=w) ok=mid,r=mid-1;
        else l=mid+1;
    }
    return y-ok+1;
}

void ask(int l,int r,int w)
{
    int ans=0;
    if(bl[l]==bl[r])
    {
        for(int i=l;i<=r;++i) 
            if(high[i]+tag[bl[l]]>=w) ans++;
        cout<<ans<<'\n';
        return;
    }
    for(int i=l;i<=R[bl[l]];++i)
        if(high[i]+tag[bl[l]]>=w) ans++;
    for(int i=L[bl[r]];i<=r;++i)
        if(high[i]+tag[bl[r]]>=w) ans++;
    for(int i=bl[l]+1;i<bl[r];++i) ans+=find(L[i],R[i],w-tag[i]);
    cout<<ans<<'\n';
}

int main()
{
    int n,m;
    read(n);
    read(m);
    for(int i=1;i<=n;++i) 
    {
        read(high[i]);
        HIGH[i]=high[i];
    }
    int siz=sqrt(n);
    for(int i=1;i<=n;++i) bl[i]=(i-1)/siz+1;
    for(int i=1;i<=bl[n];++i)
    {
        L[i]=R[i-1]+1;
        R[i]=L[i]+siz-1;
    }
    R[bl[n]]=n;
    for(int i=1;i<=bl[n];++i) sort(HIGH+L[i],HIGH+R[i]+1);
    char s[3];
    int l,r,w;
    while(m--)
    {
        scanf("%s",s);
        read(l);
        read(r);
        read(w);
        if(s[0]=='M') modify(l,r,w);
        else ask(l,r,w);
    }
    return 0;
}

 

posted @ 2017-12-20 14:56  TRTTG  阅读(184)  评论(0编辑  收藏  举报