BZOJ[4592][Shoi2015]腦洞治療儀 分塊
阿新 • • 發佈:2018-12-24
太長時間沒寫分塊了。。。寫一寫。。
碼力++
都要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;
}