首页 > 代码库 > 洛谷 U4792 Acheing 单调队列
洛谷 U4792 Acheing 单调队列
/*洛谷 U4792 Acheing 二维线段树 n*n*logn*logn T成傻逼2333 */#include<iostream>#include<cstdio>#include<cstring>#define maxn 1010#define lc k*2#define rc k*2+1#define mid (l+r)/2using namespace std;int n,m,k,g[maxn][maxn],x,y,z;int x1,x2,y1,y2,ans=0x7fffffff;int mx[maxn*4][maxn*4],mxx[maxn*4][maxn*4];void Insert_y(int kx,int k,int l,int r){ mx[kx][k]=min(mx[kx][k],z); mxx[kx][k]=max(mxx[kx][k],z); if(l==r)return; if(y<=mid)Insert_y(kx,lc,l,mid); else Insert_y(kx,rc,mid+1,r); mx[kx][k]=min(mx[kx][lc],mx[kx][rc]); mxx[kx][k]=max(mxx[kx][lc],mxx[kx][rc]);}void Insert_x(int k,int l,int r){ Insert_y(k,1,1,m); if(l==r)return; if(x<=mid)Insert_x(lc,l,mid); else Insert_x(rc,mid+1,r);}int Query_miny(int kx,int k,int l,int r){ if(y1<=l&&y2>=r)return mx[kx][k]; if(y2<=mid)return Query_miny(kx,lc,l,mid); else if(y1>mid)return Query_miny(kx,rc,mid+1,r); else return min(Query_miny(kx,lc,l,mid),Query_miny(kx,rc,mid+1,r));}int Query_maxy(int kx,int k,int l,int r){ if(y1<=l&&y2>=r)return mxx[kx][k]; if(y2<=mid)return Query_maxy(kx,lc,l,mid); else if(y1>mid)return Query_maxy(kx,rc,mid+1,r); else return max(Query_maxy(kx,lc,l,mid),Query_maxy(kx,rc,mid+1,r));}int Query_minx(int k,int l,int r){ if(x1<=l&&x2>=r)return Query_miny(k,1,1,m); if(x2<=mid)return Query_minx(lc,l,mid); else if(x1>mid)return Query_minx(rc,mid+1,r); else return min(Query_minx(lc,l,mid),Query_minx(rc,mid+1,r));}int Query_maxx(int k,int l,int r){ if(x1<=l&&x2>=r)return Query_maxy(k,1,1,m); if(x2<=mid)return Query_maxx(lc,l,mid); else if(x1>mid)return Query_maxx(rc,mid+1,r); else return max(Query_maxx(lc,l,mid),Query_maxx(rc,mid+1,r));}int main(){ scanf("%d%d%d",&n,&m,&k); memset(mxx,-127/3,sizeof(mxx)); memset(mx,127/3,sizeof(mx)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&g[i][j]); x=i;y=j;z=g[i][j]; Insert_x(1,1,n); } for(int i=k;i<=n;i++) for(int j=k;j<=m;j++){ x1=i-k+1;x2=i;y1=j-k+1;y2=j; int minner=Query_minx(1,1,n); int maxxer=Query_maxx(1,1,n); ans=min(ans,maxxer-minner); } printf("%d\n",ans); return 0;}
/*洛谷 U4792 Acheing 单调队列运用 解决二维线段树超时的问题 */#include<cstdio>#include<cstring>#define maxn 1010using namespace std;int n,m,k,g[maxn][maxn],mx[maxn][maxn],mi[maxn][maxn],mxx[maxn][maxn],mxi[maxn][maxn];int q[maxn],head,tail,ans=0x7fffffff;int init(){ int x=0,f=1;char s=getchar(); while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();} return x*f;}int min(int x,int y){ return x<y?x:y;}void Ready(){ for(int j=1;j<=m;j++){ head=1;tail=0; for(int i=1;i<=n;i++){ int x=g[i][j]; while(head<=tail&&x>g[q[tail]][j])tail--; q[++tail]=i; if(i-q[head]>=k)head++; mx[i][j]=g[q[head]][j]; } } for(int j=1;j<=m;j++){ head=1;tail=0; for(int i=1;i<=n;i++){ int x=g[i][j]; while(head<=tail&&x<g[q[tail]][j])tail--; q[++tail]=i; if(i-q[head]>=k)head++; mi[i][j]=g[q[head]][j]; } }}void Solve(){ for(int i=k;i<=n;i++){ head=1;tail=0; for(int j=1;j<=m;j++){ int x=mx[i][j]; while(head<=tail&&x>mx[i][q[tail]])tail--; q[++tail]=j; if(j-q[head]>=k)head++; mxx[i][j]=mx[i][q[head]]; } } for(int i=k;i<=n;i++){ head=1;tail=0; for(int j=1;j<=m;j++){ int x=mi[i][j]; while(head<=tail&&x<mi[i][q[tail]])tail--; q[++tail]=j; if(j-q[head]>=k)head++; mxi[i][j]=mi[i][q[head]]; } }}int main(){ n=init();m=init();k=init(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) g[i][j]=init(); Ready();Solve(); for(int i=k;i<=n;i++) for(int j=k;j<=m;j++) ans=min(ans,mxx[i][j]-mxi[i][j]); printf("%d\n",ans); return 0;}
洛谷 U4792 Acheing 单调队列
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。