分块大法好
用分快来水“xjr考考你数据结构”真是再爽不过了
xjr考考你数据结构一:虽然有点慢(6724ms)
#include<cstdio> #include<cmath> #include<cctype> #include<cstring> #include<algorithm> using namespace std; inline int read() { char ch=getchar();int sig=1,x=0; while(!isdigit(ch)) {if(ch=='-') sig=-1;ch=getchar();} while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*sig; } const int maxn=1000010; const int INF=1000000000; int n,SIZE,A[maxn]; int bl[maxn],st[maxn],en[maxn]; int maxv[maxn],minv[maxn],sumv[maxn]; void recal(int x) { maxv[x]=-INF;minv[x]=INF;sumv[x]=0; for(int i=st[x];i<=en[x];i++) { maxv[x]=max(maxv[x],A[i]); minv[x]=min(minv[x],A[i]); sumv[x]+=A[i]; } } int main() { n=read();SIZE=(int)sqrt(n); for(int i=1;i<=n;i++) { A[i]=read(); bl[i]=(i-1)/SIZE+1; en[bl[i]]=i; if(!st[bl[i]]) st[bl[i]]=i; } for(int i=1;i<=bl[n];i++) recal(i); int q=read(),l,r,x,v; while(q--) { char tp=getchar(); while(!isalpha(tp)) tp=getchar(); if(tp=='Q') { l=read();r=read(); int mx=-INF,mn=INF,sum=0; if(bl[l]==bl[r]) for(int i=l;i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i]; else { for(int i=l;i<=en[bl[l]];i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i]; for(int i=st[bl[r]];i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i]; for(int i=bl[l]+1;i<bl[r];i++) mx=max(mx,maxv[i]),mn=min(mn,minv[i]),sum+=sumv[i]; } printf("MaxNum: %d, MinNum: %d, Sum: %d\n",mx,mn,sum); } else { x=read();v=read(); A[x]=v;recal(bl[x]); } } return 0; }
xjr考考你数据结构二:加个add标记(1342ms)
#include<cstdio> #include<cmath> #include<cctype> #include<cstring> #include<algorithm> using namespace std; inline int read() { char ch=getchar();int sig=1,x=0; while(!isdigit(ch)) {if(ch=='-') sig=-1;ch=getchar();} while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*sig; } const int maxn=100010; const int INF=1000000000; int n,SIZE; int bl[maxn],st[maxn],en[maxn]; long long A[maxn],maxv[maxn],minv[maxn],sumv[maxn],add[maxn]; void recal(int x) { maxv[x]=-INF;minv[x]=INF;sumv[x]=0; for(int i=st[x];i<=en[x];i++) { maxv[x]=max(maxv[x],A[i]); minv[x]=min(minv[x],A[i]); sumv[x]+=A[i]; } } int main() { n=read();SIZE=(int)sqrt(n); for(int i=1;i<=n;i++) { A[i]=read(); bl[i]=(i-1)/SIZE+1; en[bl[i]]=i; if(!st[bl[i]]) st[bl[i]]=i; } for(int i=1;i<=bl[n];i++) recal(i); int q=read(),l,r,v; while(q--) { char tp=getchar(); while(!isalpha(tp)) tp=getchar(); if(tp=='Q') { l=read();r=read();if(l>r) swap(l,r); long long mx=-INF,mn=INF,sum=0; if(bl[l]==bl[r]) for(int i=l;i<=r;i++) mx=max(mx,A[i]+add[bl[r]]),mn=min(mn,A[i]+add[bl[r]]),sum+=A[i]+add[bl[r]]; else { for(int i=l;i<=en[bl[l]];i++) mx=max(mx,A[i]+add[bl[l]]),mn=min(mn,A[i]+add[bl[l]]),sum+=A[i]+add[bl[l]]; for(int i=st[bl[r]];i<=r;i++) mx=max(mx,A[i]+add[bl[r]]),mn=min(mn,A[i]+add[bl[r]]),sum+=A[i]+add[bl[r]]; for(int i=bl[l]+1;i<bl[r];i++) mx=max(mx,maxv[i]+add[i]),mn=min(mn,minv[i]+add[i]),sum+=sumv[i]+add[i]*(en[i]-st[i]+1); } printf("MaxNum: %lld, MinNum: %lld, Sum: %lld\n",mx,mn,sum); } else { l=read();r=read();v=read();if(l>r) swap(l,r); if(bl[l]==bl[r]) { for(int i=l;i<=r;i++) A[i]+=v; recal(bl[l]); } else { for(int i=l;i<=en[bl[l]];i++) A[i]+=v; for(int i=st[bl[r]];i<=r;i++) A[i]+=v; for(int i=bl[l]+1;i<bl[r];i++) add[i]+=v; recal(bl[l]);recal(bl[r]); } } } return 0; }
xjr考考你数据结构三:换成set标记(偷懒将维护信息和传递信息写一块了),这时间(999ms)
#include<cstdio> #include<cmath> #include<cctype> #include<cstring> #include<algorithm> using namespace std; inline int read() { char ch=getchar();int sig=1,x=0; while(!isdigit(ch)) {if(ch=='-') sig=-1;ch=getchar();} while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*sig; } const int maxn=100010; const int INF=1000000000; int n,SIZE; int bl[maxn],st[maxn],en[maxn]; long long A[maxn],maxv[maxn],minv[maxn],sumv[maxn],set[maxn]; void recal(int x) { if(set[x]) for(int i=st[x];i<=en[x];i++) A[i]=set[x]; maxv[x]=-INF;minv[x]=INF;sumv[x]=0; for(int i=st[x];i<=en[x];i++) { maxv[x]=max(maxv[x],A[i]); minv[x]=min(minv[x],A[i]); sumv[x]+=A[i]; } set[x]=0; } int main() { n=read();SIZE=(int)sqrt(n); for(int i=1;i<=n;i++) { A[i]=read(); bl[i]=(i-1)/SIZE+1; en[bl[i]]=i; if(!st[bl[i]]) st[bl[i]]=i; } for(int i=1;i<=bl[n];i++) recal(i); int q=read(),l,r,v; while(q--) { char tp=getchar(); while(!isalpha(tp)) tp=getchar(); if(tp=='Q') { l=read();r=read();if(l>r) swap(l,r); long long mx=-INF,mn=INF,sum=0; if(bl[l]==bl[r]) { if(set[bl[l]]) mx=mn=set[bl[l]],sum=set[bl[l]]*(r-l+1); else for(int i=l;i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i]; } else { if(set[bl[l]]) mx=mn=set[bl[l]],sum=set[bl[l]]*(en[bl[l]]-l+1); else for(int i=l;i<=en[bl[l]];i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i]; if(set[bl[r]]) mx=max(mx,set[bl[r]]),mn=min(mn,set[bl[r]]),sum+=set[bl[r]]*(r-st[bl[r]]+1); else for(int i=st[bl[r]];i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i]; for(int i=bl[l]+1;i<bl[r];i++) mx=max(mx,maxv[i]),mn=min(mn,minv[i]),sum+=sumv[i]; } printf("MaxNum: %lld, MinNum: %lld, Sum: %lld\n",mx,mn,sum); } else { l=read();r=read();v=read();if(l>r) swap(l,r); if(bl[l]==bl[r]) { recal(bl[l]); for(int i=l;i<=r;i++) A[i]=v; recal(bl[l]); } else { recal(bl[l]);recal(bl[r]); for(int i=l;i<=en[bl[l]];i++) A[i]=v; for(int i=st[bl[r]];i<=r;i++) A[i]=v; for(int i=bl[l]+1;i<bl[r];i++) set[i]=v,maxv[i]=minv[i]=set[i],sumv[i]=set[i]*(en[i]-st[i]+1); recal(bl[l]);recal(bl[r]); } } } return 0; }
最后是我的WZJ的数据结构(十),写的我已然TAT。(1810ms)
#include<cstdio> #include<cmath> #include<cctype> #include<cstring> #include<algorithm> using namespace std; inline int read() { char ch=getchar();int sig=1,x=0; while(!isdigit(ch)) {if(ch=='-') sig=-1;ch=getchar();} while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*sig; } const int maxn=100010; const int INF=1000000000; int n,SIZE; int bl[maxn],st[maxn],en[maxn]; long long A[maxn],maxv[maxn],minv[maxn],sumv[maxn],set[maxn],add[maxn]; void pushdown(int x) { if(set[x]) for(int i=st[x];i<=en[x];i++) A[i]=set[x]+add[x]; else for(int i=st[x];i<=en[x];i++) A[i]+=add[x]; add[x]=set[x]=0; } void recal(int x) { maxv[x]=-INF;minv[x]=INF;sumv[x]=0; for(int i=st[x];i<=en[x];i++) { maxv[x]=max(maxv[x],A[i]); minv[x]=min(minv[x],A[i]); sumv[x]+=A[i]; } } int main() { n=read();int q=read();SIZE=(int)sqrt(n); for(int i=1;i<=n;i++) { A[i]=read(); bl[i]=(i-1)/SIZE+1; en[bl[i]]=i; if(!st[bl[i]]) st[bl[i]]=i; } for(int i=1;i<=bl[n];i++) recal(i); int l,r,v; while(q--) { int t=read(); if(t==2) { l=read();r=read();if(l>r) swap(l,r); long long mx=-INF,mn=INF,sum=0; if(bl[l]==bl[r]) { if(set[bl[l]]) mx=mn=set[bl[l]],sum=set[bl[l]]*(r-l+1); else for(int i=l;i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i]; mx+=add[bl[l]];mn+=add[bl[l]];sum+=add[bl[l]]*(r-l+1); } else { if(set[bl[l]]) mx=mn=set[bl[l]]+add[bl[l]],sum=(set[bl[l]]+add[bl[l]])*(en[bl[l]]-l+1); else for(int i=l;i<=en[bl[l]];i++) mx=max(mx,A[i]+add[bl[l]]),mn=min(mn,A[i]+add[bl[l]]),sum+=A[i]+add[bl[l]]; if(set[bl[r]]) mx=max(mx,set[bl[r]]+add[bl[r]]),mn=min(mn,set[bl[r]]+add[bl[r]]),sum+=(set[bl[r]]+add[bl[r]])*(r-st[bl[r]]+1); else for(int i=st[bl[r]];i<=r;i++) mx=max(mx,A[i]+add[bl[r]]),mn=min(mn,A[i]+add[bl[r]]),sum+=A[i]+add[bl[r]]; for(int i=bl[l]+1;i<bl[r];i++) mx=max(mx,maxv[i]),mn=min(mn,minv[i]),sum+=sumv[i]; } printf("%lld %lld %lld\n",mx,mn,sum); } else { l=read();r=read();v=read();if(l>r) swap(l,r); if(bl[l]==bl[r]) { pushdown(bl[l]); if(!t) for(int i=l;i<=r;i++) A[i]=v; else for(int i=l;i<=r;i++) A[i]+=v; recal(bl[l]); } else { pushdown(bl[l]);pushdown(bl[r]); if(!t) for(int i=l;i<=en[bl[l]];i++) A[i]=v; else for(int i=l;i<=en[bl[l]];i++) A[i]+=v; if(!t) for(int i=st[bl[r]];i<=r;i++) A[i]=v; else for(int i=st[bl[r]];i<=r;i++) A[i]+=v; if(!t) for(int i=bl[l]+1;i<bl[r];i++) add[i]=0,set[i]=v,maxv[i]=minv[i]=set[i],sumv[i]=set[i]*(en[i]-st[i]+1); else for(int i=bl[l]+1;i<bl[r];i++) add[i]+=v,maxv[i]+=v,minv[i]+=v,sumv[i]+=v*(en[i]-st[i]+1); recal(bl[l]);recal(bl[r]); } } } return 0; }