• 【分块】【链表】bzoj2738 矩阵乘法


    http://www.cnblogs.com/jianglangcaijin/p/3460012.html

    首先将矩阵的数字排序。设置size,每次将size个数字插入。插入时,我们用h[i][j]记录该位置的数字是否已经插入;用sum[i][j]表示子矩阵(1,1)到(i,j)已经插入的数字个数总和。每次插入后,暴力扫一次询问,若查询子矩阵的数字个数大于等于K则答案就在此次插入的数字中;然后将该询问从链表中删除。

    怎样知道是插入的哪个数字呢?暴力O(sqrt(n))地扫描当前这段区间,依次判断这个数插入时是否恰好达到k个。

    复杂度真心不知道怎么分析了……跪了……

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<list>
     5 using namespace std;
     6 struct Ask{int x1,y1,x2,y2,k,p;
     7 Ask(const int &x){scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k); p=x;}Ask(){}};
     8 list<Ask>Q;
     9 typedef list<Ask>::iterator ITER;
    10 struct Val3{int v,x,y;}Ins[250001];
    11 bool operator < (const Val3 &a,const Val3 &b){return a.v<b.v;}
    12 int n,m,sumv[501][501],q,anss[60001];
    13 bool vis[501][501];
    14 void makeblock()
    15 {
    16     int sz=sqrt(q),sum=1; if(!sz) sz=1; 
    17     for(;sum*sz<q;++sum)
    18       {
    19           int l=(sum-1)*sz+1; int r=sum*sz;
    20           for(int i=l;i<=r;++i) vis[Ins[i].x][Ins[i].y]=1;
    21           for(int i=1;i<=n;++i)
    22             for(int j=1;j<=n;++j)
    23               sumv[i][j]=sumv[i-1][j]+sumv[i][j-1]-sumv[i-1][j-1]+vis[i][j];
    24           ITER it=Q.begin();
    25           while(it!=Q.end())
    26             {
    27                 int hav=sumv[(*it).x2][(*it).y2]-sumv[(*it).x1-1][(*it).y2]-
    28                 sumv[(*it).x2][(*it).y1-1]+sumv[(*it).x1-1][(*it).y1-1];
    29                 if(hav>=(*it).k)
    30               {
    31                 for(int i=r;i>=l;--i)
    32                   if(Ins[i].x>=(*it).x1 && Ins[i].x<=(*it).x2 &&
    33                      Ins[i].y>=(*it).y1 && Ins[i].y<=(*it).y2)
    34                        {
    35                            if(hav==(*it).k)
    36                              {
    37                                  anss[(*it).p]=Ins[i].v;
    38                                  break;
    39                              } --hav;
    40                        }
    41                 ITER t=it; ++it; Q.erase(t);
    42               }
    43             else ++it;
    44             }
    45       }
    46     int l=(sum-1)*sz+1; int r=q;
    47     for(int i=l;i<=r;++i) vis[Ins[i].x][Ins[i].y]=1;
    48     for(int i=1;i<=n;++i)
    49       for(int j=1;j<=n;++j)
    50           sumv[i][j]=sumv[i-1][j]+sumv[i][j-1]-sumv[i-1][j-1]+vis[i][j];
    51     ITER it=Q.begin();
    52     while(it!=Q.end())
    53       {
    54           int hav=sumv[(*it).x2][(*it).y2]-sumv[(*it).x1-1][(*it).y2]-
    55             sumv[(*it).x2][(*it).y1-1]+sumv[(*it).x1-1][(*it).y1-1];
    56           if(hav>=(*it).k)
    57           {
    58             for(int i=r;i>=l;--i)
    59               if(Ins[i].x>=(*it).x1 && Ins[i].x<=(*it).x2 &&
    60                  Ins[i].y>=(*it).y1 && Ins[i].y<=(*it).y2)
    61                    {
    62                      if(hav==(*it).k)
    63                        {
    64                            anss[(*it).p]=Ins[i].v;
    65                            break;
    66                        } --hav;
    67                   }
    68             ITER t=it; ++it; Q.erase(t);
    69           }
    70         else ++it;
    71       }
    72 }
    73 int main()
    74 {
    75     scanf("%d%d",&n,&m);
    76     for(int i=1;i<=n;++i)
    77       for(int j=1;j<=n;++j)
    78         {
    79             scanf("%d",&Ins[++q].v);
    80             Ins[q].x=i; Ins[q].y=j;
    81         }
    82     sort(Ins+1,Ins+q+1);
    83     for(int i=1;i<=m;++i) Q.push_back(Ask(i));
    84     makeblock();
    85     for(int i=1;i<=m;++i) printf("%d
    ",anss[i]);
    86     return 0;
    87 }
  • 相关阅读:
    2.25
    2.24
    2.22
    influxdb 配置
    mongodb 数据备份
    influxDb数据备份
    Linux 及 git 指令集合
    git 项目 保存至gitee中
    TypeScripte 资料
    SecureCrt 的配色方案
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4147429.html
Copyright © 2020-2023  润新知