1. 程式人生 > >BZOJ[4592][Shoi2015]腦洞治療儀 分塊

BZOJ[4592][Shoi2015]腦洞治療儀 分塊

太長時間沒寫分塊了。。。寫一寫。。
碼力++
都要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; }