【Luogu】P2801教主的魔法(分块)

  题目链接

  激动qwq。这是我A的第一道分块。

  分块之后对块内元素暴力sort。修改的时候对于整块打个标记,查询的时候只需要查C-tag就行了

  对于非整块,暴力修改,改完之后sort

  对于查询……非整块暴力查询,整块二分C-tag的位置就好啦

  

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#define maxn 1000010
#define sqtn 1200
using namespace std;

inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

struct Node{
    int dat,id;
    bool operator <(const Node a)const{
        return dat<a.dat;
    }
};

struct Block{
    Node q[sqtn];
    int tag,tot;
    Block(){memset(q,0,sizeof(q));    tag=tot=0;    }
}que[sqtn];
int d[maxn];
int s[maxn];
int w[maxn];
int le[sqtn],ri[sqtn];

void sorten(int x){
    Block &o=que[x];
    sort(o.q+1,o.q+o.tot+1);
    for(int i=1;i<=o.tot;++i){
        w[o.q[i].id]=i;
    }
}

int main(){
    int n=read(),m=read();
    int sqt=sqrt(n),blo=0;
    for(int i=1;i<=n;++i){
        d[i]=read();
        s[i]=(i-1)/sqt+1;
        if(s[i]>blo)    blo=s[i];
        ri[s[i]]=i;
    }
    for(int i=n;i>=1;--i){
        le[s[i]]=i;
        que[s[i]].q[++que[s[i]].tot]=(Node){d[i],i};
    }
    for(int i=1;i<=blo;++i)    sorten(i);
    for(int i=1;i<=m;++i){
        char c[10];int x,y,z;
        scanf("%s%d%d%d",c,&x,&y,&z);
        if(c[0]=='M'){
            int to=min(ri[s[x]],y);
            for(int j=x;j<=to;++j)    que[s[x]].q[w[j]].dat+=z;
            sorten(s[x]);
            if(s[x]==s[y])    continue;
            int from=max(le[s[y]],x);
            for(int j=from;j<=y;++j)    que[s[y]].q[w[j]].dat+=z;
            sorten(s[y]);
            for(int j=s[x]+1;j<s[y];++j)    que[j].tag+=z;
        }
        else if(c[0]=='A'){
            int to=min(ri[s[x]],y),ans=0;
            for(int j=x;j<=to;++j)
                if(que[s[x]].q[w[j]].dat>=z)    ans++; 
            if(s[x]==s[y]){
                printf("%d\n",ans);
                continue;
            }
            int from=max(le[s[y]],x);
            for(int j=from;j<=y;++j){
                //printf("%d\n",que[s[y]].q[w[j]].dat);
                if(que[s[y]].q[w[j]].dat>=z)    ans++;
            }
            for(int j=s[x]+1;j<s[y];++j){
                Block now=que[j];
                int l=1,r=now.tot,lim=r+1;
                while(l<=r){
                    int mid=(l+r)>>1;
                    if(now.q[mid].dat>=z-now.tag){
                        lim=mid;
                        r=mid-1;
                    }
                    else    l=mid+1;
                }
                ans+=now.tot-lim+1;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
/*
5 3
1 2 3 4 5
A 1 5 4
M 3 5 1
A 1 5 4
*/

 

posted @ 2018-01-20 10:36  Konoset  阅读(141)  评论(0编辑  收藏  举报