• [BZOJ 2738]矩阵乘法


    [BZOJ 2738]矩阵乘法

    题目

    给你一个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

    OUTPUT

    1

    3

    解题报告

    一开始打了树状数组套主席树,然后$MLE+RE$不断= =

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 using namespace std;
     6 inline int read(){
     7     int sum(0);
     8     char ch(getchar());
     9     for(;ch<'0'||ch>'9';ch=getchar());
    10     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
    11     return sum;
    12 }
    13 int n,q;
    14 int a[505][505],num[250005];
    15 int size,cnt;
    16 inline int lowbit(int x){
    17     return x&-x;
    18 }
    19 int rt[250005],lch[30000005],rch[30000005],sum[30000005];
    20 inline void update(int &x,int las,int pos,int w,int l,int r){
    21     x=++cnt;
    22     lch[x]=lch[las];
    23     rch[x]=rch[las];
    24     sum[x]=sum[las]+w;
    25     if(l==r)
    26         return;
    27     int mid((l+r)>>1);
    28     if(pos<=mid)
    29         update(lch[x],lch[las],pos,w,l,mid);
    30     else
    31         update(rch[x],rch[las],pos,w,mid+1,r);
    32 }
    33 int l,r,L[30],R[30];
    34 inline int query(int l,int r,int k){
    35     if(l==r)
    36         return l;
    37     int mid((l+r)>>1),suml(0),sumr(0);
    38     for(int i=1;i<=l;++i)
    39         suml+=sum[lch[L[i]]];
    40     for(int i=1;i<=r;++i)
    41         sumr+=sum[lch[R[i]]];
    42     if(k<=sumr-suml){
    43         for(int i=1;i<=l;++i)
    44             L[i]=lch[L[i]];
    45         for(int i=1;i<=r;++i)
    46             R[i]=lch[R[i]];
    47         return query(l,mid,k);
    48     }
    49     else{
    50         for(int i=1;i<=l;++i)
    51             L[i]=rch[L[i]];
    52         for(int i=1;i<=r;++i)
    53             R[i]=rch[R[i]];
    54         return query(mid+1,r,k-(sumr-suml));
    55     }
    56 }
    57 int main(){
    58     n=read(),q=read();
    59     for(int i=1;i<=n;++i)
    60         for(int j=1;j<=n;++j)
    61             a[i][j]=read(),num[(i-1)*n+j]=a[i][j];
    62     sort(num+1,num+n*n+1);
    63     size=unique(num+1,num+n*n+1)-num-1;
    64     int edge(n*n);
    65     for(int i=1;i<=n;++i)
    66         for(int j=1;j<=n;++j){
    67             a[i][j]=lower_bound(num+1,num+size+1,a[i][j])-num;
    68             for(int k=(i-1)*n+j;k<=edge;k+=lowbit(k))
    69                 update(rt[k],rt[k],a[i][j],1,1,size);
    70         }
    71     while(q--){
    72         int aa(read()),b(read()),c(read()),d(read()),k(read());
    73         for(int i=aa;i<=c;++i){
    74             for(int j=1;j<b;++j)
    75                 for(int k=j;k<=edge;k+=lowbit(k))
    76                     update(rt[k],rt[k],a[i][j],-1,1,size);
    77             for(int j=d+1;j<=n;++j)
    78                 for(int k=j;j<=edge;k+=lowbit(k))
    79                     update(rt[k],rt[k],a[i][j],-1,1,size);
    80         }
    81         l=r=0;
    82         int tp1((aa-1)*n+b-1),tp2((c-1)*n+d);
    83         for(int i=tp1;i>0;i-=lowbit(i))
    84             L[++l]=rt[i];
    85         for(int i=tp2;i>0;i-=lowbit(i))
    86             R[++r]=rt[i];
    87         printf("%d
    ",num[query(1,size,k)]);
    88         for(int i=aa;i<=c;++i){
    89             for(int j=1;j<b;++j)
    90                 for(int k=j;k<=edge;k+=lowbit(k))
    91                     update(rt[k],rt[k],a[i][j],1,1,size);
    92             for(int j=d+1;j<=n;++j)
    93                 for(int k=j;j<=edge;k+=lowbit(k))
    94                     update(rt[k],rt[k],a[i][j],1,1,size);
    95         }
    96     }
    97 }
    MLE的主席树

    正解:

    我们把所有点按权值从小到大排序,一次插入$n$个点,用前缀和维护一下

    然后,用链表维护询问,每到一个询问,查看一下当前询问矩阵有多少个数,假如大于$k$,说明答案已经加入矩阵,倒序查询即可

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 using namespace std;
     6 inline int read(){
     7     int sum(0);
     8     char ch(getchar());
     9     for(;ch<'0'||ch>'9';ch=getchar());
    10     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
    11     return sum;
    12 }
    13 struct data{
    14     int x,y,num;
    15     inline bool operator<(const data &gg)const{
    16         return num<gg.num;
    17     }
    18 }nod[250005];
    19 int cnt;
    20 struct query{
    21     int a,b,c,d,k;
    22 }que[60005];
    23 int ans[60005];
    24 int n,q;
    25 int map[505][505];
    26 int pre[60005],nxt[60005];
    27 int c[505][505],sum[505][505];
    28 inline bool check(data x,int a,int b,int c,int d){
    29     return x.x>=a&&x.x<=c&&x.y>=b&&x.y<=d;
    30 }
    31 inline void del(int x){
    32     pre[nxt[x]]=pre[x];
    33     nxt[pre[x]]=nxt[x];
    34 }
    35 int main(){
    36     n=read(),q=read();
    37 //  cout<<n<<" "<<q<<endl;
    38     for(int i=1;i<=n;++i)
    39         for(int j=1;j<=n;++j){
    40             map[i][j]=read();
    41             nod[++cnt].x=i;
    42             nod[cnt].y=j;
    43             nod[cnt].num=map[i][j];
    44         }
    45 //  cout<<cnt<<endl;
    46     sort(nod+1,nod+cnt+1);
    47     for(int i=1;i<=q;++i){
    48         que[i].a=read(),que[i].b=read(),que[i].c=read(),que[i].d=read(),que[i].k=read();
    49         pre[i]=i-1,nxt[i]=i+1;
    50     }
    51     nxt[0]=1;
    52     for(int i=1;i<=n;++i){
    53         int sta((i-1)*n+1),en(i*n);
    54 //      cout<<"???"<<sta<<' '<<en<<endl;
    55         for(int j=sta;j<=en;++j)
    56             c[nod[j].x][nod[j].y]=1;
    57 //      cout<<"check the whole count array"<<endl;
    58 //      for(int j=1;j<=n;++j,cout<<endl)
    59 //          for(int k=1;k<=n;++k)
    60 //              cout<<c[j][k]<<' ';
    61         for(int j=1;j<=n;++j)
    62             for(int k=1;k<=n;++k)
    63                 sum[j][k]=sum[j-1][k]+sum[j][k-1]-sum[j-1][k-1]+c[j][k];
    64 //      cout<<"check the whole sum array"<<endl;
    65 //      for(int j=1;j<=n;++j,cout<<endl)
    66 //          for(int k=1;k<=n;++k)
    67 //              cout<<sum[j][k]<<' ';
    68         for(int j=nxt[0];j<=q;j=nxt[j]){
    69 //          cout<<j<<endl;
    70             int a(que[j].a),b(que[j].b),c(que[j].c),d(que[j].d),k(que[j].k);
    71             int s(sum[c][d]-sum[a-1][d]-sum[c][b-1]+sum[a-1][b-1]);
    72 //          cout<<j<<' '<<s<<' '<<k<<' '<<que[j].k<<endl;
    73             if(s<k)
    74                 continue;
    75 //          cout<<"not break?"<<s<<' '<<k<<endl;
    76             for(int l=en;l>=sta;--l){
    77                 if(check(nod[l],a,b,c,d)){
    78 //                  cout<<"init?"<<s<<' '<<k<<endl;
    79                     if(s==k){
    80                         ans[j]=nod[l].num;
    81 //                      cout<<"fuzhi?? "<<l<<' '<<nod[l].num<<endl;
    82                         del(j);
    83                         break;
    84                     }
    85                     else
    86                         --s;
    87                 }
    88             }
    89         }
    90     }
    91     for(int i=1;i<=q;++i)
    92         printf("%d
    ",ans[i]);
    93 }
    AC Code

    暴力主席树不可取= =

  • 相关阅读:
    CentOS 7下PXE+Kickstart无人值守安装操作系统
    利用pentestbox打造ms17-010移动"杀器"
    XSS测试代码
    sublime Text3基本配置记录+python
    CTF中那些脑洞大开的编码和加密
    信息安全相关资源
    RIP 实验
    python输出有色记录
    下载Chrome商店和Youtube资源
    mysql使用问题记录
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7607601.html
Copyright © 2020-2023  润新知