BZOJ[4592][Shoi2015]脑洞治疗仪 分块

传送门ber~

太长时间没写分块了。。。写一写。。
码力++
都要NOI了还在刷水....

代码如下:

#include<algorithm>
#include<ctype.h>
#include<cstdio>
#include<cmath>
#define N 200050
using namespace std;
inline int read(){
    int x=0,f=1;char c;
    do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
    do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
    return x*f;
}
int n,m,block_size,sum,ans,l,r,t;
int a[N],block[N],siz[N],cnt[N],ml[N],mr[N],bl[N],br[N],b[N],mx[N];
inline void pushdown(int k){
    if(b[k]==1){
        for(int i=bl[k];i<=br[k];i++)
            a[i]=0;
    }
    if(b[k]==2){
        for(int i=bl[k];i<=br[k];i++)
            a[i]=1;
    }
    b[k]=0;
}
inline void recount(int k){
    cnt[k]=0;
    int p=0;
    mx[k]=0;
    for(int i=bl[k];i<=br[k];i++){
        if(a[i]==0) p++;
        else p=0;
        mx[k]=max(mx[k],p);
        cnt[k]=cnt[k]+a[i];
    }
    ml[k]=siz[k];
    for(int i=bl[k];i<=br[k];i++)
        if(a[i]==1){
            ml[k]=i-bl[k];
            break;
        }
    mr[k]=siz[k];
    for(int i=br[k];i>=bl[k];i--)
        if(a[i]==1){
            mr[k]=br[k]-i;
            break;
        }
}
inline void Debug(){
    for(int j=1;j<=block[n];j++){
         printf("ml:%d mr:%d mx:%d cnt:%d\n",ml[j],mr[j],mx[j],cnt[j]);
    }
}
int main(){
    n=read();m=read();
    block_size=sqrt(n);
    for(int i=1;i<=n;i++){
        a[i]=1;
        block[i]=(i-1)/block_size+1;
        cnt[block[i]]=(++siz[block[i]]);
        if(!bl[block[i]]) bl[block[i]]=i;
        br[block[i]]=i;
    }
    for(int i=1;i<=m;i++){
        t=read();
        if(!t){
            l=read();r=read();
            if(block[r]-block[l]<2){
                pushdown(block[l]);pushdown(block[r]);
                for(int j=l;j<=r;j++)
                    a[j]=0;
                recount(block[l]);recount(block[r]);
            }
            else{
                for(int j=block[l]+1;j<block[r];j++){
                    b[j]=1;
                    mx[j]=ml[j]=mr[j]=siz[j];
                    cnt[j]=0;
                }
                pushdown(block[l]);pushdown(block[r]);
                for(int j=l;j<=br[block[l]];j++)
                    a[j]=0;
                for(int j=bl[block[r]];j<=r;j++)
                    a[j]=0;
                recount(block[l]);recount(block[r]);
            }
        }
        else if(t==1){
            l=read();r=read();
            sum=0;
            if(block[r]-block[l]<2){
                pushdown(block[l]);pushdown(block[r]);
                for(int j=l;j<=r;j++)
                    if(a[j]==1) sum++,a[j]=0;
                recount(block[l]);recount(block[r]);
            }
            else{
                for(int j=block[l]+1;j<block[r];j++){
                    sum=sum+cnt[j];
                    b[j]=1;
                    mx[j]=ml[j]=mr[j]=siz[j];
                    cnt[j]=0;
                }
                pushdown(block[l]);pushdown(block[r]);
                for(int j=l;j<=br[block[l]];j++)
                    if(a[j]==1) sum++,a[j]=0;
                for(int j=bl[block[r]];j<=r;j++)
                    if(a[j]==1) sum++,a[j]=0;
                recount(block[l]);recount(block[r]);
            }
            l=read();r=read();
            if(block[r]-block[l]<2){
                pushdown(block[l]);pushdown(block[r]);
                for(int j=l;j<=r && sum;j++)
                    if(a[j]==0) a[j]=1,sum--;
                recount(block[l]);recount(block[r]);
            }
            else{
                pushdown(block[l]);
                for(int j=l;j<=br[block[l]] && sum;j++)
                    if(a[j]==0) a[j]=1,sum--;
                recount(block[l]);
                for(int j=block[l]+1;j<block[r] && sum;j++){
                    if(siz[j]-cnt[j]>sum){
                        pushdown(j);
                        for(int l=bl[j];l<=br[j] && sum;l++)
                            if(a[l]==0) a[l]=1,sum--;
                        recount(j);
                        break;
                    }
                    else{
                        sum=sum-(siz[j]-cnt[j]);
                        b[j]=2;
                        mx[j]=ml[j]=mr[j]=0;
                        cnt[j]=siz[j];
                    }
                }
                pushdown(block[r]);
                for(int j=bl[block[r]];j<=r && sum;j++)
                    if(a[j]==0) a[j]=1,sum--;
                recount(block[r]);
            }
        }
        else{
            l=read();r=read();
            ans=sum=0;
            if(block[r]-block[l]<2){
                pushdown(block[l]);pushdown(block[r]);
                for(int j=l;j<=r;j++){
                    if(a[j]==0) sum++;
                    else sum=0;
                    ans=max(sum,ans);
                }
                printf("%d\n",ans);
            }
            else{
                pushdown(block[l]);
                for(int j=l;j<=br[block[l]];j++){
                    if(a[j]==0) sum++;
                    else sum=0;
                    ans=max(sum,ans);
                }
                for(int j=block[l]+1;j<block[r];j++){
                    sum=sum+ml[j];ans=max(ans,sum);
                    ans=max(ans,mx[j]);
                    if(siz[j]==ml[j]) continue;
                    else sum=mr[j],ans=max(ans,sum);
                }
                pushdown(block[r]);
                for(int j=bl[block[r]];j<=r;j++){
                    if(a[j]==0) sum++;
                    else sum=0;
                    ans=max(sum,ans);
                }
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/waduan2/article/details/80892955