[BZOJ 2738] 矩阵乘法 · 分块

来源:互联网 发布:c语言bool是什么 编辑:程序博客网 时间:2024/05/17 23:23

标算整体二分,然而窝太弱了并不会做。

分块大法好:狠狠点我

我们把n*n个数排序,然后从小到大插入矩阵,每次插n个,用前缀和维护每个子矩阵当前已经填了多少个数。

查找的时候 对于每个询问,如果子矩阵里的数已经超过了k个,说明答案在当前插入的这n个数里,倒着查找即可。

用链表维护询问,已经出解的直接跳过。

因为每个询问最多会查n次,所以复杂度O(nq),然而如果用树状数组代替前缀和维护的话是O(nqlog^2),妥妥T。

#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;const int N=505;struct arr{int x,y,num;bool operator <(const arr &A)const{return num<A.num;}}data[N*N];struct typ{int x1,x2,y1,y2,k;}query[60005];int n,m,t[N][N],c[N][N],x,i,j,k,p,s,ans[60005];int pre[N*N],suf[N*N];int x1,x2,y1,y2;int main(){scanf("%d%d",&n,&m);for (i=1;i<=n;i++)for (j=1;j<=n;j++){scanf("%d",&x);data[i*n-n+j].x=i;data[i*n-n+j].y=j;data[i*n-n+j].num=x;}sort(data+1,data+n*n+1);for (i=1;i<=m;i++){scanf("%d%d%d%d%d",&query[i].x1,&query[i].y1,&query[i].x2,&query[i].y2,&query[i].k);suf[i]=i+1;pre[i]=i-1;}suf[0]=1;memset(t,0,sizeof t);for (i=1;i<=n;i++){int q=i*n-n+1,w=i*n;for (j=q;j<=w;j++)c[data[j].x][data[j].y]=1;for (j=1;j<=n;j++)for (k=1;k<=n;k++)t[j][k]=c[j][k]+t[j-1][k]+t[j][k-1]-t[j-1][k-1];for (j=suf[0];j<=m;j=suf[j]){x1=query[j].x1;x2=query[j].x2;y1=query[j].y1;y2=query[j].y2;s=t[x2][y2]+t[x1-1][y1-1]-t[x1-1][y2]-t[x2][y1-1];if (s<query[j].k) continue;for (p=w;p>=q;p--)if (data[p].x>=x1 && data[p].x<=x2 && data[p].y>=y1 && data[p].y<=y2) if (s==query[j].k) {ans[j]=data[p].num;suf[pre[j]]=suf[j];pre[suf[j]]=pre[j];break;}else s--;}}for (i=1;i<=m;i++)printf("%d\n",ans[i]);return 0;}


0 0
原创粉丝点击