求问分块询问

P4344 [SHOI2015] 脑洞治疗仪

@[听取MLE声一片](/user/253738) 写分块题解的教皇有空帮蒟蒻看一下吗![](//图.tk/0)
by Balor @ 2023-06-10 17:46:06


@[Balor](/user/1010254) 你是写错了球调还是什么?
by 听取MLE声一片 @ 2023-06-10 17:53:25


看看我的题解。 >遍历每个块,如果当前块 0 的个数比 res 大就一个一个填,接着结束,否则就区间直接填入。
by 听取MLE声一片 @ 2023-06-10 17:53:59


@[听取MLE声一片](/user/253738) 是想求调,也想问一下这个询问的正确性
by Balor @ 2023-06-10 17:54:23


@[听取MLE声一片](/user/253738) 思路除了询问和您的题解差不离
by Balor @ 2023-06-10 17:55:24


@[Balor](/user/1010254) 马蜂差距很大实现也有差异我也不好看啊。 你可以去查查块重构之类的问题![](//图.tk/q)
by 听取MLE声一片 @ 2023-06-10 18:05:31


@[听取MLE声一片](/user/253738) 呃呃,我发现问题所在了…… 最后 更新 $Y$ 的时候没有考虑到 $w_Y$![](//图.tk/q),但是还是 WA 了一些
by Balor @ 2023-06-10 18:05:43


写错了一堆东西。。。放一下调完后开O2能过的代码: ```cpp #include<bits/stdc++.h> using namespace std; const int N=3e5+10,M=1e3+10; int n,m,st[M],ed[M],one[M],l[M],r[M],cs[M],bar[N],tag[M],Len,cnt; bool a[N]; int len(int k){return ed[k]-st[k]+1;} void pushdown(int k){ if(tag[k]==-1)return; for(int i=st[k];i<=ed[k];i++)a[i]=tag[k]; tag[k]=-1;return; } void pushup(int k){ int now=0;l[k]=-1;r[k]=-1;one[k]=cs[k]=0; for(int i=st[k];i<=ed[k];i++)if(a[i])l[k]=i-st[k],i=ed[k]+1; for(int i=ed[k];i>=st[k];i--)if(a[i])r[k]=ed[k]-i,i=st[k]-1; for(int i=st[k];i<=ed[k];i++)if(a[i])cs[k]=max(cs[k],now),now=0;else now++; cs[k]=max(cs[k],now); if(l[k]<0)l[k]=len(k);if(r[k]<0)r[k]=len(k); for(int i=st[k];i<=ed[k];i++)one[k]+=a[i]; return; } void init(){ Len=sqrt(n);cnt=n/Len+bool(n%Len); for(int i=1;i<=cnt;i++){ st[i]=ed[i-1]+1;ed[i]=i*Len; for(int j=st[i];j<=ed[i];j++)bar[j]=i,a[j]=1; tag[i]=-1;one[i]=len(i); }one[cnt]-=ed[cnt]-n;ed[cnt]=n; return; } void debug(){ for(int i=1;i<=cnt;i++)pushdown(i),pushup(i); for(int i=1;i<=cnt;i++){ for(int j=st[i];j<ed[i];j++)printf("%d ",a[j]); printf("%d|",a[ed[i]]); }puts(""); for(int i=1;i<=cnt;i++)printf("%d %d %d %d %d|",l[i],r[i],cs[i],one[i],tag[i]); puts("\n-----"); return; } int modify(int x,int y){ int X=bar[x],Y=bar[y],ret=0; if(X==Y){ pushdown(X); for(int i=x;i<=y;i++)ret+=a[i]; for(int i=x;i<=y;i++)a[i]=0; pushup(X);return ret; } for(int i=X+1;i<=Y-1;i++)ret+=one[i],tag[i]=one[i]=0,l[i]=r[i]=cs[i]=len(i); pushdown(X);for(int i=x;i<=ed[X];i++)ret+=a[i],a[i]=0;pushup(X); pushdown(Y);for(int i=st[Y];i<=y;i++)ret+=a[i],a[i]=0;pushup(Y); // debug(); return ret; } void update(int x,int y,int val){ int X=bar[x],Y=bar[y]; if(X==Y){ pushdown(X); for(int i=x;i<=y&&val;i++)if(!a[i])a[i]=val--; pushup(X);return; } pushdown(X); for(int i=x;i<=ed[X]&&val;i++)if(!a[i])a[i]=val--; pushup(X); if(!val)return; for(int i=X+1;i<=Y-1&&val;i++){ if(val<len(i)-one[i]){ pushdown(i); for(int j=st[i];j<=ed[i]&&val;j++)if(!a[j])a[j]=val--; pushup(i); return; } val-=len(i)-one[i]; tag[i]=1;one[i]=len(i);l[i]=r[i]=cs[i]=0; } if(!val)return; pushdown(Y); for(int i=st[Y];i<=y&&val;i++)if(!a[i])a[i]=val--; pushup(Y); // debug(); return; } int query(int x,int y){ int X=bar[x],Y=bar[y],ret=0,now=0; if(X==Y){ pushdown(X);pushup(X); for(int i=x;i<=y;i++)if(a[i])ret=max(ret,now),now=0;else now++; return max(ret,now); } pushdown(X);pushup(X); for(int i=x;i<=ed[X];i++)if(a[i])ret=max(ret,now),now=0;else now++;ret=max(ret,now); for(int i=X+1;i<=Y-1;i++){ ret=max(ret,cs[i]); if(!one[i])now+=len(i),ret=max(ret,now); else now+=l[i],ret=max(ret,now),now=r[i]; } pushdown(Y);pushup(Y); for(int i=st[Y];i<=y;i++)if(a[i])ret=max(ret,now),now=0;else now++;ret=max(ret,now); return ret; } signed main(){ scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;i++){ int opt,L,R,L_=0,R_=0; scanf("%d%d%d",&opt,&L,&R); if(opt==0)modify(L,R); else if(opt==1)scanf("%d%d",&L_,&R_),opt=modify(L,R),update(L_,R_,opt); else if(opt==2)printf("%d\n",query(L,R)); } system("pause"); return 0; } ``` ~~大帝写的代码甚至要优化,我是不是小常数体质啊~~
by Balor @ 2023-06-13 17:21:49


|