BZOJ2738: 矩阵乘法(整体二分)

Description

  给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数。

Input

  第一行两个数N,Q,表示矩阵大小和询问组数;
  接下来N行N列一共N*N个数,表示这个矩阵;
  再接下来Q行每行5个数描述一个询问:x1,y1,x2,y2,k表示找到以(x1,y1)为左上角、以(x2,y2)为右下角的子矩形中的第K小数。

Output

  对于每组询问输出第K小的数。

Sample Input

2 2
2 1
3 4
1 2 1 2 1
1 1 2 2 3

Sample Output

1
3

HINT 

  矩阵中数字是109以内的非负整数;

  20%的数据:N<=100,Q<=1000;

  40%的数据:N<=300,Q<=10000;

  60%的数据:N<=400,Q<=30000;

  100%的数据:N<=500,Q<=60000。

解题思路:

整体二分思想非常浓。

将点权排序,二分mid时加入前mid个答案。

在二维树状数组上+1

最后二维树状数组查询前缀合就知道区间有多少个数。

最后统计答案就好了。

代码:

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 struct data{
  5     int i,j;
  6     int val;
  7 }d[500000];
  8 struct que{
  9     int px,py,qx,qy;
 10     int no;
 11     int val;
 12 }q[100010],ss[100010],sp[100010];
 13 int line[501][501];
 14 int n,Q;
 15 int cnt;
 16 int top;
 17 int ans[1000000];
 18 int lowbit(int x)
 19 {
 20     return x&(-x);
 21 }
 22 void update(int x,int y,int v)
 23 {
 24     for(int i=x;i<=n;i+=lowbit(i))
 25     {
 26         for(int j=y;j<=n;j+=lowbit(j))
 27         {
 28             line[i][j]+=v;
 29         }
 30     }
 31     return ;
 32 }
 33 int query(int x,int y)
 34 {
 35     int ans=0;
 36     for(int i=x;i;i-=lowbit(i))
 37     {
 38         for(int j=y;j;j-=lowbit(j))
 39         {
 40             ans+=line[i][j];
 41         }
 42     }
 43     return ans;
 44 }
 45 bool cmp(data x,data y)
 46 {    
 47     return x.val<y.val;
 48 }
 49 void Insert(int no,int dir)
 50 {
 51     update(d[no].i,d[no].j,dir);
 52     return ;
 53 }
 54 int sum(int no)
 55 {
 56     int ret=0;
 57     ret=query(q[no].qx,q[no].qy)+query(q[no].px-1,q[no].py-1);
 58     ret-=query(q[no].qx,q[no].py-1)+query(q[no].px-1,q[no].qy);
 59     return ret;
 60 }
 61 void macrs(int l,int r,int ll,int rr)
 62 {
 63     if(ll>rr)
 64         return ;
 65     if(l==r)
 66     {
 67         for(int i=ll;i<=rr;i++)
 68             ans[q[i].no]=d[l].val;
 69         return ;
 70     }
 71     int mid=(l+r)>>1;
 72     while(top<mid)
 73         Insert(++top,1);
 74     while(top>mid)
 75         Insert(top--,-1);
 76     int sta1=0,sta2=0;
 77     for(int i=ll;i<=rr;i++)
 78     {
 79         if(sum(i)>=q[i].val)
 80             sp[++sta1]=q[i];
 81         else
 82             ss[++sta2]=q[i];
 83     }
 84     int sta=ll-1,lmid;
 85     for(int i=1;i<=sta1;i++)
 86         q[++sta]=sp[i];
 87     lmid=sta;
 88     for(int i=1;i<=sta2;i++)
 89         q[++sta]=ss[i];
 90     macrs(l,mid,ll,lmid);
 91     macrs(mid+1,r,lmid+1,rr);
 92     return ;
 93 }
 94 int main()
 95 {
 96     scanf("%d%d",&n,&Q);
 97     for(int i=1;i<=n;i++)
 98         for(int j=1;j<=n;j++)
 99         {
100             int tmp;
101             scanf("%d",&tmp);
102             d[++cnt]=(data){i,j,tmp};
103         }
104     std::sort(d+1,d+cnt+1,cmp);
105     for(int i=1;i<=Q;i++)
106     {
107         scanf("%d%d%d%d%d",&q[i].px,&q[i].py,&q[i].qx,&q[i].qy,&q[i].val);
108         if(q[i].px>q[i].qx)
109             std::swap(q[i].px,q[i].qx);
110         if(q[i].py>q[i].qy)
111             std::swap(q[i].py,q[i].qy);
112         q[i].no=i;
113     }
114     macrs(1,cnt,1,Q);
115     for(int i=1;i<=Q;i++)
116         printf("%d\n",ans[i]);
117     return 0;
118 }

 

 

 

posted @ 2018-12-13 20:03  Unstoppable728  阅读(277)  评论(0编辑  收藏  举报