Bzoj2738 矩阵乘法

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 1471  Solved: 632

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。

 

Source

 

分治 整体二分

二分一个答案,然后处理所有询问,把答案小于当前尝试值的和大于当前值的询问分别递归处理。

54行的保护机制似乎并没有什么用,一定要像74和76行那样加上if判断才能防止爆炸,迷。

  1 /*by SilverN*/
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<vector>
  8 using namespace std;
  9 const int mxn=510;
 10 int read(){
 11     int x=0,f=1;char ch=getchar();
 12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 14     return x*f;
 15 }
 16 struct num{
 17     int x,y,w;
 18     bool operator < (const num b)const{
 19         return w<b.w;
 20     }
 21 }a[mxn*mxn];
 22 int t[mxn][mxn];
 23 int n;
 24 void add(int x,int y,int v){
 25     while(x<=n){
 26         int tmp=y;
 27         while(tmp<=n){t[x][tmp]+=v; tmp+=tmp&-tmp;}
 28         x+=x&-x;
 29     }
 30     return;
 31 }
 32 int smm(int x,int y){
 33     int res=0;
 34     while(x){
 35         int tmp=y;
 36         while(tmp){res+=t[x][tmp]; tmp-=tmp&-tmp;}
 37         x-=x&-x;
 38     }
 39     return res;
 40 }
 41 inline int ask(int x1,int y1,int x2,int y2){
 42     return smm(x2,y2)-smm(x1-1,y2)-smm(x2,y1-1)+smm(x1-1,y1-1);
 43 }
 44 struct query{
 45     int x1,y1,x2,y2;
 46     int k,id;
 47 }q[mxn*120];
 48 int now[mxn*120],tmp[mxn*120];
 49 int ans[mxn*120];
 50 int Q,ed;
 51 void solve(int l,int r,int L,int R){//答案区间,询问区间 
 52 //    printf("l:%d r:%d L:%d R:%d\n",l,r,L,R);
 53     if(l>r || L>R)return;
 54 //    if(l==r)return;
 55     int mid=(a[l].w+a[r].w)>>1;
 56     int i,j,cnt=0;
 57     for(i=l;i<=r && a[i].w<=mid;i++){add(a[i].x,a[i].y,1);++cnt;}
 58     int el=L-1,er=R+1,c;
 59     for(i=L;i<=R;i++){
 60         c=now[i];
 61         int res=ask(q[c].x1,q[c].y1,q[c].x2,q[c].y2);
 62         if(res>=q[c].k){
 63             ans[q[c].id]=mid;
 64             tmp[++el]=c;
 65         }
 66         else{//res<q[c].k
 67             tmp[--er]=c;
 68             q[c].k-=res;
 69         }
 70     }
 71     for(i=l;i<=r && a[i].w<=mid;i++){add(a[i].x,a[i].y,-1);}
 72     for(i=L;i<=R;i++){now[i]=tmp[i];}
 73 //    if(l+cnt-1!=r || el!=R)solve(l,l+cnt-1,L,el);
 74     if(l+cnt-1!=r || el!=R)solve(l,l+cnt-1,L,el);
 75 //    if(l+cnt!=l || er!=L) solve(l+cnt,r,er,R);
 76     if(l+cnt!=l || er!=L) solve(l+cnt,r,er,R);
 77     return;
 78 }
 79 int tct=0;
 80 int main(){
 81 //    freopen("in.txt","r",stdin);
 82     int i,j,x;
 83     n=read();Q=read();
 84     ed=n*n;
 85     for(i=1;i<=n;i++)
 86         for(j=1;j<=n;j++){
 87             a[++tct].x=i; a[tct].y=j;
 88             a[tct].w=read();
 89         }
 90     sort(a+1,a+ed+1);
 91     for(i=1;i<=Q;i++){
 92         q[i].x1=read();    q[i].y1=read();
 93         q[i].x2=read();    q[i].y2=read();
 94         q[i].k=read();  q[i].id=i;
 95         now[i]=i;
 96     }
 97     solve(1,ed,1,Q);
 98     for(i=1;i<=Q;i++)printf("%d\n",ans[i]);
 99     return 0;
100 }

 

posted @ 2017-03-20 14:39  SilverNebula  阅读(174)  评论(0编辑  收藏  举报
AmazingCounters.com