BZOJ_2738_Matrix Multiplication_Overall Bisection

BZOJ_2738_Matrix Multiplication_Overall Bisection

Description

  Give you an N*N matrix, don't do matrix multiplication, but ask for the Kth decimal of a subrectangle each time.

Input

  The first line has two numbers N, Q, which represent the size of the matrix and the number of query groups;
  the next N rows and N columns have a total of N*N numbers, which represent this matrix;
  then the next Q line has 5 numbers in each row to describe a query: x1 ,y1,x2,y2,k means to find the Kth decimal in the sub-rectangle with (x1,y1) as the upper left corner and (x2,y2) as the lower right corner.

Output

  Output the Kth smallest number for each set of queries.

Sample Input

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

Sample Output

1
3

HINT

  The numbers in the matrix are non-negative integers within 109;
  20% of the data: N<=100, Q<=1000;
  40% of the data: N<=300, Q<=10000;
  60% of the data: N<=400 ,Q<=30000;
  100% data: N<=500,Q<=60000.


 You can go offline and sort the weights.

solve(b,e,l,r) means that the answers to the queries from b to e are within the weights ranging from l to r.

If the answer is mid, insert the first number of mids, and then query the number of intervals, which can be maintained with a two-dimensional tree array.

If the answer is on the left, go left, and if it is on the right, subtract the contribution from the left and go right.

 

Code:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 60050
int n,c[550][550],L[N],R[N],mid[N],ans[N];
struct A {
    int v,x,y;
}a[550*550];
struct Q {
    int d,f,g,h,k,id;
}q[N],t[N];
bool cmp(const A &a,const A &b) {
    return a.v<b.v;
}
void fix(int x,int y,int v) {
    int i,j;
    for(i=x;i<=n;i+=i&(-i)) {
        for(j=y;j<=n;j+=j&(-j)) {
            c[i][j]+=v;
        }
    }
}
int inq (int x, int y) {
    int i,j,re=0;
    for(i=x;i;i-=i&(-i)) {
        for(j=y;j;j-=j&(-j)) {
            re+=c[i][j];
        }
    }
    return re;
}
int query(int x,int y,int x2,int y2) {
    x--; and--;
    return inq(x2,y2)-inq(x,y2)-inq(x2,y)+inq(x,y);
}
void solve(int b,int e,int l,int r) {
    int i;
    if(b>e) return ;
    if(l==r) {
        for(i=b;i<=e;i++) {
            ans[q[i].id]=a[l].v;
        }
        return ;
    }
    int mid=(l+r)>>1,lpos=b,rpos=e;
    for(i=l;i<=mid;i++) {
        fix(a[i].x,a[i].y,1);
    }
    for(i=b;i<=e;i++) {
        int sizls=query(q[i].d,q[i].f,q[i].g,q[i].h);
        if(sizls>=q[i].k) t[lpos++]=q[i];
        else q[i].k-=sizls,t[rpos--]=q[i];
    }
    for(i=b;i<=e;i++) q[i]=t[i];
    for(i=l;i<=mid;i++) {
        fix(a[i].x,a[i].y,-1);
    }
    solve(b,lpos-1,l,mid);
    solve(rpos+1,e,mid+1,r);
}
int main() {
    int m;
    scanf("%d%d",&n,&m);
    int i, tot = 0, j;  
    for(i=1;i<=n;i++) {
        for(j=1;j<=n;j++) {
            scanf("%d",&a[++tot].v);
            a [tot] .x = i; a [tot] .y = j;
        }
    }
    sort(a+1,a+n*n+1,cmp);
    for(i=1;i<=m;i++) {
        scanf("%d%d%d%d%d",&q[i].d,&q[i].f,&q[i].g,&q[i].h,&q[i].k);
        q[i].id=i;
    }
    solve(1,m,1,n*n);
    for(i=1;i<=m;i++) printf("%d\n",ans[i]);
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325016971&siteId=291194637