BZOJ 2738: 矩阵乘法|分块|整体二分
2016-03-02 15:25
288 查看
对所有数先排序然后每次插入n个数,然后处理每个询问
如果子矩阵中的数大于k则一定答案一定在这n个数当中,然后暴力查找
整体二分加树状数组的做法非常经典
Orz_fqk神犇
(以下代码是他的,不过我修改了一个地方,在二分的时候可以严格按照原区间成半二分,这样会快一点)
如果子矩阵中的数大于k则一定答案一定在这n个数当中,然后暴力查找
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<vector> #include<queue> #include<cmath> #include<set> #include<map> #define N 633333 using namespace std; int sc() { int i=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar(); return i*f; } struct Q{int x1,x2,y1,y2,k,ans;}q ; struct W{int x,y,v;}b ; int a[505][505],sum[505][505]; int n,m,mx,cnt,fa ; int find(int x) { return (fa[x]==x||fa[x]==0)?fa[x]=x:fa[x]=find(fa[x]); } bool cmp(W a,W b){return a.v<b.v;} int main() { n=sc(),m=sc(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) b[++cnt].x=i, b[cnt].y=j, b[cnt].v=sc(); sort(b+1,b+cnt+1,cmp); for(int i=1;i<=m;i++) q[i].x1=sc(),q[i].y1=sc(),q[i].x2=sc(),q[i].y2=sc(),q[i].k=sc(); for(int k=1;k<=n;k++) { for(int j=1;j<=n;j++) { int x=k*n-n+j; a[b[x].x][b[x].y]++; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]; for(int i=find(1);i<=m;i=find(i+1)) { int x1=q[i].x1-1,x2=q[i].x2; int y1=q[i].y1-1,y2=q[i].y2; int temp=sum[x2][y2]-sum[x1][y2]-sum[x2][y1]+sum[x1][y1]; if(temp<q[i].k)continue; temp-=q[i].k; for(int x=k*n;x;x--) if(b[x].x>x1&&b[x].x<=x2&&b[x].y>y1&&b[x].y<=y2) if(!temp--) { q[i].ans=b[x].v; break; } fa[i]=i+1; } } for(int i=1;i<=m;i++)printf("%d\n",q[i].ans); return 0; }
整体二分加树状数组的做法非常经典
Orz_fqk神犇
(以下代码是他的,不过我修改了一个地方,在二分的时候可以严格按照原区间成半二分,这样会快一点)
#include<iostream> #include<cstdio> #include<vector> #include<algorithm> #define inf 1000000007 using namespace std; int n,Q,now,cnt; int tree[505][505]; struct node {int x,y,z;} a[250005]; int ans[60005]; struct query {int x1,x2,y1,y2,k,id;} q[60005],q1[60005],q2[60005]; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline int lowbit(int i) { return i&(-i); } inline bool operator<(node a,node b) { return a.z<b.z; } inline void add(int x,int y,int val) { for (int i=x;i<=n;i+=lowbit(i)) for (int j=y;j<=n;j+=lowbit(j)) tree[i][j]+=val; } inline int query(int x,int y) { int tmp=0; for (int i=x;i;i-=lowbit(i)) for (int j=y;j;j-=lowbit(j)) tmp+=tree[i][j]; return tmp; } void solve(int t,int w,int l,int r) { if (t>w) return; if (l==r) { for (int i=t;i<=w;i++) ans[q[i].id]=a[l].z; return; } int mid=l+r>>1; while (a[now].z<=a[mid].z) now++,add(a[now].x,a[now].y,1); while (a[now].z>a[mid].z) add(a[now].x,a[now].y,-1),now--; int p1=0,p2=0; for (int i=t;i<=w;i++) { int tmp=query(q[i].x2,q[i].y2)+query(q[i].x1-1,q[i].y1-1)-query(q[i].x1-1,q[i].y2)-query(q[i].x2,q[i].y1-1); if (tmp>q[i].k-1) q1[++p1]=q[i]; else q2[++p2]=q[i]; } for (int i=1;i<=p1;i++) q[t+i-1]=q1[i]; for (int i=1;i<=p2;i++) q[t+p1+i-1]=q2[i]; solve(t,t+p1-1,l,mid); solve(t+p1,w,mid+1,r); } int main() { n=read(); Q=read(); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[++cnt].x=i,a[cnt].y=j,a[cnt].z=read(); sort(a+1,a+cnt+1); for (int i=1;i<=Q;i++) q[i].x1=read(),q[i].y1=read(),q[i].x2=read(),q[i].y2=read(),q[i].k=read(),q[i].id=i; solve(1,Q,1,cnt); for (int i=1;i<=Q;i++) printf("%d\n",ans[i]); return 0; }
相关文章推荐
- [BZOJ2038][2009国家集训队][莫队][分块]小z的袜子
- Codeforces538F A Heap of Heaps【分块+差分求前缀和】
- 大矩阵的分块乘法及matlab实现
- Hadoop分块和分片
- bzoj-2741 L
- bzoj-3585 mex
- bzoj-2051 A Problem For Fun
- 算法马拉松8(差和问题)
- 1290 Counting Diff Pairs
- 【国家集训队2012】【BZOJ2738】矩阵乘法
- 【Violet 6】【BZOJ2724】蒲公英
- 【BZOJ4320】Homework
- 【BZOJ4216】Pig
- 【BZOJ2741】FOTILE模拟赛 L
- [2009国家集训队]小Z的袜子(hose) 分块做法
- NBUT 1457 分块
- codeforces #307 E. GukiZ and GukiZiana (分块)
- Codeforces Round #307 (Div. 2)E. GukiZ and GukiZiana(分块)
- 【分块】 CF 551 E GukiZ and GukiZiana
- Codeforces Round #307 (Div. 2) E. GukiZ and GukiZiana (分块)