Bzoj2639: 矩形计算

Time Limit: 20 Sec  Memory Limit: 256 MB
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列的连线为对角线的子矩阵的权值。

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

Sample Output

8
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 }

 

本文为博主原创文章,转载请注明出处。
posted @ 2017-05-06 18:31  SilverNebula  阅读(278)  评论(0编辑  收藏  举报
AmazingCounters.com