Bzoj2639: 矩形计算
Submit: 178 Solved: 94
Description
输入一个n*m的矩阵,矩阵的每一个元素都是一个整数,然后有q个询问,每次询问一个子矩阵的权值。矩阵的权值是这样定义的,对于一个整数x,如果它在该矩阵中出现了p次,那么它给该矩阵的权值就贡献p2。
Input
第一行两个整数n,m表示矩阵的规模。
接下来n行每行m个整数,表示这个矩阵的每个元素。
再下来一行一个整数q,表示询问个数。
接下来q行每行四个正整数x1,y1,x2,y2,询问以第x1行第y1列和第x2行第y2列的连线为对角线的子矩阵的权值。
接下来n行每行m个整数,表示这个矩阵的每个元素。
再下来一行一个整数q,表示询问个数。
接下来q行每行四个正整数x1,y1,x2,y2,询问以第x1行第y1列和第x2行第y2列的连线为对角线的子矩阵的权值。
Output
输出q行每行一个整数回答对应询问。
Sample Input
3 4
1 3 2 1
1 3 2 4
1 2 3 4
8
1 2 2 1
1 1 2 1
1 1 3 4
1 1 1 1
2 2 3 3
3 4 2 2
1 3 3 1
2 4 3 4
1 3 2 1
1 3 2 4
1 2 3 4
8
1 2 2 1
1 1 2 1
1 1 3 4
1 1 1 1
2 2 3 3
3 4 2 2
1 3 3 1
2 4 3 4
Sample Output
8
4
38
1
8
12
27
4
4
38
1
8
12
27
4
HINT
对于全部数据
1<=n,m<=200
q<=100000
|矩阵元素大小|<=2*109
Source
分治 分块 二维莫队
二维的莫队算法
分块的时候按顶点坐标分块,belong= $ (x1/\sqrt {n} )* \sqrt m + (y1/\sqrt m)$
范围转移的时候稍有点麻烦
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #define LL long long 7 using namespace std; 8 const int mxn=310; 9 int read(){ 10 int x=0,f=1;char ch=getchar(); 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 inline void write(int x){ 16 if(x<0) putchar('-'),x=-x; 17 if(x>9) write(x/10); 18 putchar(x%10+'0'); 19 return; 20 } 21 int n,m,Q; 22 int mp[mxn][mxn]; 23 int bas[mxn*mxn],cc=0; 24 int cnt[mxn*mxn],hs[mxn*mxn]; 25 struct query{ 26 int x1,y1,x2,y2; 27 int m,id; 28 bool operator < (const query &b)const{ 29 return (m==b.m && ((x1==b.x1 && y1<b.y1) || x1<b.x1 )) || m<b.m; 30 } 31 }q[100010]; 32 int nowans=0,ans[100010]; 33 inline void add(int x){ 34 nowans+=cnt[x]*2+1; ++cnt[x]; return; 35 } 36 inline void del(int x){ 37 nowans-=cnt[x]*2-1; --cnt[x]; return; 38 } 39 void solve(){ 40 int l=1,r=0,u=1,d=0;//初始位置 41 int i,j; 42 for(i=1;i<=Q;i++){ 43 while(r<q[i].y2){++r;for(j=u;j<=d;j++)add(mp[j][r]);} 44 while(l>q[i].y1){--l;for(j=u;j<=d;j++)add(mp[j][l]);} 45 while(d<q[i].x2){++d;for(j=l;j<=r;j++)add(mp[d][j]);} 46 while(u>q[i].x1){--u;for(j=l;j<=r;j++)add(mp[u][j]);} 47 // 48 // 49 while(r>q[i].y2){for(j=u;j<=d;j++)del(mp[j][r]);--r;} 50 while(l<q[i].y1){for(j=u;j<=d;j++)del(mp[j][l]);++l;} 51 while(d>q[i].x2){for(j=l;j<=r;j++)del(mp[d][j]);--d;} 52 while(u<q[i].x1){for(j=l;j<=r;j++)del(mp[u][j]);++u;} 53 ans[q[i].id]=nowans; 54 } 55 return; 56 } 57 int main(){ 58 int i,j; 59 n=read();m=read(); 60 for(i=1;i<=n;i++) 61 for(j=1;j<=m;j++){ 62 mp[i][j]=read(); 63 bas[++cc]=mp[i][j]; 64 } 65 sort(bas+1,bas+cc+1); 66 int ed=unique(bas+1,bas+cc+1)-bas-1; 67 for(i=1;i<=n;i++) 68 for(j=1;j<=m;j++){ 69 int tmp=lower_bound(bas+1,bas+ed+1,mp[i][j])-bas; 70 mp[i][j]=tmp; 71 }//离散化 72 Q=read(); 73 int sn=sqrt(n),sm=sqrt(m); 74 for(i=1;i<=Q;i++){ 75 q[i].x1=read(); q[i].y1=read(); 76 q[i].x2=read(); q[i].y2=read(); 77 if(q[i].x1>q[i].x2)swap(q[i].x1,q[i].x2); 78 if(q[i].y1>q[i].y2)swap(q[i].y1,q[i].y2); 79 q[i].m=(q[i].x1/sn)*sm+(q[i].y1/sm); 80 q[i].id=i; 81 } 82 sort(q+1,q+Q+1); 83 solve(); 84 for(i=1;i<=Q;i++){ 85 write(ans[i]); 86 puts(""); 87 } 88 return 0; 89 }
本文为博主原创文章,转载请注明出处。