BZOJ4972 八月月赛 Problem B 小Q的方格纸 二维前缀和
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ4972 八月月赛Problem B
题目概括
一个矩阵,一坨询问,问矩阵中一个特定方向的等腰直角三角形范围的sum。
题解
一开始毫无头绪。
看完9题,一题也不会。
发现这题A的人多,于是我花了15分钟仔细思考。
发现可以了。
对于一个三角形区域,我们可以看下图:
我们把求右下黑色三角形区域转化成一个矩形和3个左上的三角形,然后就OK了。
矩形只要前缀和就可以了,O(nm)
求贴在上面和左边的,各自只要O(nm)
询问O(1)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #include <cstdio> #include <algorithm> #include <cstring> #include <cstdlib> #include <cmath> using namespace std; typedef unsigned int uint; const int N=3000+5; const uint Inv=534566745; uint A,B,C,x,y,k,t,a[N][N],sum[N][N],L[N][N*2],U[N][N]; int n,m,q; uint rng61(){ A^=A<<16,A^=A>>5,A^=A<<1,t=A,A=B,B=C,C^=t^A; return C; } uint Pow(uint x, int y){ if (y==0) return 1; uint xx=Pow(x,y/2); xx*=xx; if (y&1) xx*=x; return xx; } uint val( int xa, int ya, int xb, int yb){ xb=min(xb,n),yb=min(yb,m); return sum[xb][yb]-sum[xb][ya-1]-sum[xa-1][yb]+sum[xa-1][ya-1]; } int main(){ scanf ( "%d%d%d%u%u%u" ,&n,&m,&q,&A,&B,&C); memset (sum,0, sizeof sum); memset (L,0, sizeof L); memset (U,0, sizeof U); for ( int i=1;i<=n;i++) for ( int j=1;j<=m;j++){ a[i][j]=rng61(); sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j]; } for ( int i=n;i>=1;i--) for ( int j=1;j<=m*2;j++) L[i][j]=L[i+1][j-1]+val(i,1,i,j); for ( int i=m;i>=1;i--) for ( int j=1;j<=n;j++) U[i][j]=U[i+1][j-1]+val(1,i,j,i); uint timesx=Pow(233,q),Ans=0; for ( int i=1;i<=q;i++){ timesx*=Inv; x=rng61()%n+1,y=rng61()%m+1,k=rng61()%min(x,y)+1; int xx=x,yy=y,kk=k; uint ans=sum[x][y]-L[1][x+y-k-1]+L[x+1][max(0,yy-kk-1)]+U[y+1][max(0,xx-kk-1)]; Ans+=timesx*ans; } printf ( "%u" ,Ans); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步