BZOJ 2738 矩阵乘法 整体二分+二维树状数组

来源:互联网 发布:网络系统集成就业前景 编辑:程序博客网 时间:2024/04/28 17:06

先吐槽一下这道题的题目———————-
这道题要求出所有询问的解并且所有问题的解都具有单调性,所以我们很容易能想出来这道题应该要整体二分,这道题的瓶颈是如何快速统计出来一个数到底在区间内排第几,其实看到矩形我们就应该想到树状数组,将所有大于当前二分答案的格子设为1,其余设为零,用树状数组求和,就可快速判断满不满足当前解为第K大,另外还可将所有点按照V值排序,这样每次二分出一个新的答案就可从之前的位置扫,还有当了l>r时一定要跳出,否则超时!!!

#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>#include<cstring>#include<string>#include<iostream>#include<iomanip>#include<algorithm>using namespace std;#define maxn 521struct ma{    int x,y,val;    void read()    {        scanf("%d",&val);    }    bool operator <(ma b) const    {        return val<b.val;    }}a[maxn*maxn];struct my_query{    int x1,y1,x2,y2,k,num;    void read()    {        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k);    }}q[600001],nq[600001];int c[maxn][maxn];int n,m;void add(int l,int r,int val){    for(int i=l;i<=n;i+=i&-i)        for(int j=r;j<=n;j+=j&-j)            c[i][j]+=val;}int query(int l,int r){    int re=0;    for(int i=l;i;i-=i&-i)        for(int j=r;j;j-=j&-j)            re+=c[i][j];    return re;}int ans[600001];int now;void fen(int x,int y,int l,int r){    int mid=x+y>>1;    if(x>y || l>r) return;    while(a[now+1].val<=mid && now!=n*n)    {        now++;        add(a[now].x,a[now].y,1);    }    while(a[now].val>mid && now)    {        add(a[now].x,a[now].y,-1);        now--;    }    int _l=l,_r=r;    for(int i=l;i<=r;i++)    {        int temp=query(q[i].x2,q[i].y2)+query(q[i].x1-1,q[i].y1-1)-query(q[i].x1-1,q[i].y2)-query(q[i].x2,q[i].y1-1);        if(q[i].k<=temp)        {            ans[q[i].num]=mid;            nq[_l++]=q[i];        }        else nq[_r--]=q[i];    }    memcpy(q+l,nq+l,sizeof(q[0])*(r-l+1));    fen(x,mid-1,l,_l-1);    fen(mid+1,y,_r+1,r);}int main(){    scanf("%d%d",&n,&m);    int max_num=0;    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)        {            a[i*n-n+j].x=i;            a[i*n-n+j].y=j;            a[i*n-n+j].read();            if(a[i*n-n+j].val>max_num) max_num=a[i*n-n+j].val;        }    for(int i=1;i<=m;i++)    {        q[i].read();        q[i].num=i;    }    sort(a+1,a+1+n*n);    fen(0,max_num,1,m);    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);    return 0;}
0 1