bzoj2738: 矩阵乘法

来源:互联网 发布:java窗体的猜数字游戏 编辑:程序博客网 时间:2024/05/16 08:12

链接

  http://www.lydsy.com/JudgeOnline/problem.php?id=2738

题解

  我百度了题解发现是整体二分,点开黄学长的题解看了看,然后就自行脑补了一个整体二分。写的不仅丑而且常数巨大。不太想深入学,因为考到的概率确实不大。
  其实表面上叫做整体二分,实现起来也确实像二分,但算法的实质是分治。
  大致思想就是二分答案,然后看看哪些询问的答案比二分的答案大,哪些小,递归分治下去。
  这道题就可以二分答案mid,每次把权值小于等于mid的数对应位置上+1(可以用二维BIT实现)。然后扫描当前的询问,对于一个询问看它对应的那个子矩形中已经插入了几个数,如果插入的数的个数比询问的k大,就说明枚举的答案过大,就把当前询问加入左边,否则加入右边。
  然后分治下去。

代码

//整体二分、二维BIT#include <cstdio>#include <algorithm>#define maxn 510#define maxq 70000#define lowbit(x) (x&-x)using namespace std;int bit[maxn][maxn], x1[maxq], x2[maxq], y1[maxq], y2[maxq], ans[maxq], w[maxn][maxn],    N, Q, k[maxq], xu[maxn*maxn], p, x[maxn*maxn], y[maxn*maxn];void add(int x, int y, int v){    int i, j;    for(i=x;i<=N;i+=lowbit(i))        for(j=y;j<=N;j+=lowbit(j))bit[i][j]+=v;}int sum(int x, int y){    int ans=0, i, j;    for(i=x;i;i-=lowbit(i))for(j=y;j;j-=lowbit(j))ans+=bit[i][j];    return ans;}int q(int n){return sum(x2[n],y2[n])-sum(x1[n],y2[n])-sum(x2[n],y1[n])+sum(x1[n],y1[n]);}void bin(int *num, int l, int r){    int i, j, mid=l+r>>1, lq[num[0]+5], rq[num[0]+5];    if(l==r){for(i=1;i<=num[0];i++)ans[num[i]]=mid;return;}    while(w[x[xu[p+1]]][y[xu[p+1]]]<=mid)p++,add(x[xu[p]],y[xu[p]],1);    while(w[x[xu[p]]][y[xu[p]]]>mid and p)add(x[xu[p]],y[xu[p]],-1),p--;    lq[0]=rq[0]=0;    for(i=1;i<=num[0];i++)    {        if(q(num[i])>=k[num[i]])lq[++lq[0]]=num[i];        else rq[++rq[0]]=num[i];    }    if(lq[0])bin(lq,l,mid);    if(rq[0])bin(rq,mid+1,r);}int read(int x=0){    char c=getchar();    while(c<48 or c>57)c=getchar();    while(c>=48 and c<=57)x=(x<<1)+(x<<3)+c-48, c=getchar();    return x;}bool cmp(int a, int b){return w[x[a]][y[a]]<w[x[b]][y[b]];}void init(){    int i, j, t;    N=read(), Q=read();    for(i=1;i<=N;i++)for(j=1;j<=N;j++)w[i][j]=read();    for(i=1;i<=Q;i++)        x1[i]=read()-1, y1[i]=read()-1, x2[i]=read(), y2[i]=read(), k[i]=read();    for(i=1;i<=N;i++)for(j=1;j<=N;j++)    {        t=(i-1)*N+j;        xu[t]=t;        x[t]=i, y[t]=j;    }    w[0][0]=0x7fffffff;    sort(xu+1,xu+N*N+1,cmp);}int main(){    int i, num[maxq];    init();    for(i=1;i<=Q;i++)num[i]=i;num[0]=Q;    bin(num,1,1e9);    for(i=1;i<=Q;i++)printf("%d\n",ans[i]);    return 0;}
0 0
原创粉丝点击