BZOJ 3343: 教主的魔法|分块

来源:互联网 发布:tp框架去掉index.php 编辑:程序博客网 时间:2024/04/28 05:30

分块暴力对每一个块排序,询问如果跨过了整个块,那么就查询整个块,对排好序的块二分答案,两边在块外的就暴力排序,二分答案
区间修改如果跨过了整个块,就在块上标记,否则暴力修改,重新给块排序

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<set>#include<map>#include<iostream>#include<algorithm>using namespace std;int sc(){    int i=0;char c=getchar();    while(c>'9'||c<'0')c=getchar();    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();    return i;}int a[1000005],block_st[1005][1005],block_tag[1005],block_sum[1005];int bl[1000005],st[2222];int block,m,n;bool cmp(int a,int b){return a>b;}int find(int *w,int r,int K){    int l=1,ans=0;    while(l<=r)    {        int mid=l+r>>1;        if(w[mid]>=K)ans=mid,l=mid+1;        else r=mid-1;    }    return ans;}int main(){    n=sc(),m=sc();block=sqrt(n);    for(int i=1;i<=n;i++)a[i]=sc();    for(int i=1;i<=n;i++)    {        bl[i]=(i-1)/block+1;        block_sum[(i-1)/block+1]++;        block_st[(i-1)/block+1][block_sum[(i-1)/block+1]]=a[i];    }    for(int i=1;i*block+1<=n;i++)        sort(block_st[i]+1,block_st[i]+block_sum[i]+1,cmp);    for(int i=1;i<=m;i++)    {        char s[5]; scanf("%s",s);        if(s[0]=='A')        {            int l=sc(),r=sc(),k=sc();            if(bl[l]==bl[r])            {                int top=0;                for(int j=l;j<=r;j++)st[++top]=a[j];                sort(st+1,st+top+1,cmp);                printf("%d\n",find(st,top,k));            }            else            {                int x=bl[l],y=bl[r];                int ans=0,top=0;                for(int j=x+1;j<y;j++)                    ans+=find(block_st[j],block_sum[j],k-block_tag[j]);                for(int j=l;bl[j]==bl[l];j++) st[++top]=a[j]+block_tag[x];                for(int j=r;bl[j]==bl[r];j--) st[++top]=a[j]+block_tag[y];                sort(st+1,st+top+1,cmp);                printf("%d\n",ans+find(st,top,k));            }           }        else        {            int l=sc(),r=sc(),k=sc();            if(bl[l]==bl[r])            {                for(int j=l;j<=r;j++)a[j]+=k;                int top=0,x=bl[l];                for(int j=(x-1)*block+1;bl[j]==x;j++)block_st[x][++top]=a[j];                sort(block_st[x]+1,block_st[x]+top+1,cmp);            }            else            {                int x=bl[l],y=bl[r],top;                for(int j=x+1;j<y;j++)block_tag[j]+=k;                for(int j=l;bl[j]==x;j++)a[j]+=k;                for(int j=r;bl[j]==y;j--)a[j]+=k;                top=0;                for(int j=(x-1)*block+1;bl[j]==x;j++)block_st[x][++top]=a[j];                sort(block_st[x]+1,block_st[x]+top+1,cmp);                top=0;                for(int j=(y-1)*block+1;bl[j]==y;j++)block_st[y][++top]=a[j];                sort(block_st[y]+1,block_st[y]+top+1,cmp);            }        }    }    return 0;}
0 0