bzoj 4592(洛谷 4344) [Shoi2015]脑洞治疗仪——线段树上二分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4592
1操作就是用线段树来二分找到第一个有 k 个0的位置。
在洛谷上A了,与暴力和网上题解对拍也都没问题。在bzoj上4msWA。不知道为什么。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ls Ls[cr] #define rs Rs[cr] using namespace std; const int N=2e5+5,M=N<<1; int n,m,sm[M],fl[M],fr[M],mx[M],Ls[M],Rs[M],lz[M],tot; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return fx?ret:-ret; } void build(int l,int r,int cr) { sm[cr]=r-l+1; lz[cr]=-1; if(l==r)return; int mid=l+r>>1; ls=++tot; build(l,mid,ls); rs=++tot; build(mid+1,r,rs); } void pshd(int cr,int l,int mid,int r) { if(lz[cr]==-1)return; fl[ls]=fr[ls]=mx[ls]=(lz[cr]?0:mid-l+1); sm[ls]=(lz[cr]?mid-l+1:0); fl[rs]=fr[rs]=mx[rs]=(lz[cr]?0:r-mid); sm[rs]=(lz[cr]?r-mid:0); lz[ls]=lz[rs]=lz[cr]; lz[cr]=-1; } void pshp(int cr) { sm[cr]=sm[ls]+sm[rs]; fl[cr]=fl[ls]+(sm[ls]?0:fl[rs]); fr[cr]=fr[rs]+(sm[rs]?0:fr[ls]); mx[cr]=max(max(fl[cr],fr[cr]),max(mx[ls],mx[rs])); mx[cr]=max(mx[cr],fr[ls]+fl[rs]); } void mdfy(int l,int r,int cr,int L,int R,bool k) { if(l>=L&&r<=R) { fl[cr]=fr[cr]=mx[cr]=(k?0:r-l+1); sm[cr]=(k?r-l+1:0); lz[cr]=k; return; } int mid=l+r>>1; pshd(cr,l,mid,r); if(L<=mid)mdfy(l,mid,ls,L,R,k); if(mid<R)mdfy(mid+1,r,rs,L,R,k); pshp(cr); } int qry(int l,int r,int cr,int L,int R) { if(l>=L&&r<=R) return sm[cr]; int mid=l+r>>1,ret=0; pshd(cr,l,mid,r); if(L<=mid) ret=qry(l,mid,ls,L,R); if(mid<R) ret+=qry(mid+1,r,rs,L,R); return ret; } int fnd(int l,int r,int cr,int L,int R,int k) { if(l==r)return l; int mid=l+r>>1; pshd(cr,l,mid,r); if(l>=L&&r<=R) { int siz=mid-l+1-sm[ls]; if(siz>=k)return fnd(l,mid,ls,L,R,k); return fnd(mid+1,r,rs,L,R,k-siz); } if(mid<L)return fnd(mid+1,r,rs,L,R,k); if(R<=mid)return fnd(l,mid,ls,L,R,k); int d=qry(l,mid,ls,L,R); d=mid-max(l,L)+1-d;//L!!!!//max!!!!!probably just r>R if(d>=k) return fnd(l,mid,ls,L,R,k); return fnd(mid+1,r,rs,L,R,k-d); } int query(int l,int r,int cr,int L,int R) { if(l>=L&&r<=R)return mx[cr]; int mid=l+r>>1; pshd(cr,l,mid,r); if(mid<L) return query(mid+1,r,rs,L,R); if(R<=mid) return query(l,mid,ls,L,R); int ret=max(query(l,mid,ls,L,R),query(mid+1,r,rs,L,R)); ret=max(ret,min(fr[ls],mid-L+1)+min(fl[rs],R-mid));///// } void print() { for(int i=1;i<=n;i++) printf("%d ",qry(1,n,1,i,i)); puts(""); } int main() { n=rdn(); m=rdn(); tot=1; build(1,n,1); for(int i=1,op,l,r,l1,r1,d,k;i<=m;i++) { op=rdn(); l=rdn(); r=rdn(); if(!op) { mdfy(1,n,1,l,r,0); } if(op==1) { l1=rdn(); r1=rdn(); d=qry(1,n,1,l,r); if(!d)continue; mdfy(1,n,1,l,r,0); k=qry(1,n,1,l1,r1); if(r1-l1+1-k<=d) mdfy(1,n,1,l1,r1,1); else { k=fnd(1,n,1,l1,r1,d); mdfy(1,n,1,l1,k,1); } } if(op==2) { printf("%d\n",query(1,n,1,l,r)); } } return 0; }
附上暴力和maker和对拍,以便之后查。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2e5+5; int n,m,ans; bool a[N]; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return fx?ret:-ret; } int main() { n=rdn(); m=rdn(); for(int i=1;i<=n;i++)a[i]=1; for(int i=1,op,l,r,l1,r1,d;i<=m;i++) { op=rdn(); l=rdn(); r=rdn(); if(!op) { for(int j=l;j<=r;j++)a[j]=0; } if(op==1) { l1=rdn(); r1=rdn(); d=0; for(int j=l;j<=r;j++)d+=a[j],a[j]=0; for(int j=l1;j<=r1&&d;j++) d-=(!a[j]),a[j]=1; } if(op==2) { d=0; ans=0; for(int j=l;j<=r;j++) if(!a[j])d++; else ans=max(ans,d),d=0; ans=max(ans,d); printf("%d\n",ans); } } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<ctime> using namespace std; const int N=2e5,M=10; int n,m,op,l,r; int main() { srand(time(0)); n=rand()%N+1; m=rand()%N+1; printf("%d %d\n",n,m); for(int i=1;i<=m;i++) { op=rand()%M; if(op>=3)op=2; l=rand()%n+1; r=rand()%n+1; if(l>r)swap(l,r); if(op==1) { printf("%d %d %d ",op,l,r); l=rand()%n+1; r=rand()%n+1; if(l>r)swap(l,r); printf("%d %d\n",l,r); } else printf("%d %d %d\n",op,l,r); } return 0; }
#include<cstdio> #include<algorithm> using namespace std; int cnt; int main() { while(1) { system("./maker > data.in"); system("./a < data.in > zj.out"); system("./b < data.in > bl.out"); if(system("diff zj.out bl.out"))return 0; cnt++; printf("cnt=%d\n",cnt); if(cnt==500)return 0; } }