zoukankan      html  css  js  c++  java
  • SDU暑期集训排位(6)题解

    L - Olympiad Training

    $FWT$。首先,观察到$n$很小,我们可以想办法求出每个子集的答案,但是$m$很大,直接枚举子集的方法肯定行不通。不妨考虑对每个$topic$单独考虑贡献,设当前考虑的是第$j$个$topic$,然后枚举最大值,设$a_{ij}$为最大值,其他的人我们只能选比它小的,设我们能选出的最大的集合为$mask$,显然,对于$mask$子集$s$,如果$s$包含第$i$个人,答案就需要加上$a_{ij}$,如果不包含,它的最大值就为其他值,我们不妨分两步完成这个操作,首先,对于$mask$的所有子集加上答案$a_{ij}$,然后,设$mask'$为$mask$去掉$i$之后的集合,我们对$mask'$的所有子集减去$a_{ij}$,到此为止,如果我们能快速完成给子集同时加上一个数这个操作,这个题就做完了,$and$运算的$FWT$支持此操作。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<vector>
     4 #include<algorithm>
     5 const int N=22;
     6 int n,q,m;
     7 typedef long long ll;
     8 ll f[1<<20],ans[22];
     9 typedef std::pair<int,int> P;
    10 std::vector<P> g[10004];
    11 void FWT(ll *a,int n) {
    12     for(int i=1;i<n;i<<=1)
    13         for(int p=i<<1,j=0;j<n;j+=p)
    14             for(int k=0;k<i;k++)
    15                 a[j+k]+=a[i+j+k];
    16 }
    17 int main() {
    18     int T;
    19     scanf("%d",&T);
    20     while(T--) {
    21         scanf("%d%d%d",&n,&m,&q);
    22         for(int i=0;i<1<<n;i++) f[i]=0;
    23         for(int i=0;i<m;i++) g[i].clear();
    24         for(int i=0;i<n;i++) {
    25             for(int j=0,x;j<m;j++) {
    26                 scanf("%d",&x);
    27                 g[j].push_back(P(x,i));
    28             }
    29         }
    30         for(int i=0;i<m;i++) {
    31             std::sort(g[i].begin(),g[i].end());
    32             int mask=0;
    33             for(P c:g[i]) {
    34                 mask|=1<<c.second;
    35                 f[mask]+=c.first;
    36                 f[mask^(1<<c.second)]-=c.first;
    37             }
    38         }
    39         FWT(f,1<<n);
    40         for(int i=1;i<=n;i++) ans[i]=1e18;
    41         for(int i=1;i<1<<n;i++) {
    42             int k=0;
    43             for(int j=0;j<n;j++) if(i>>j&1) ++k;
    44             ans[k]=std::min(ans[k],f[i]);
    45         }
    46         for(int k;q--;) {
    47             scanf("%d",&k);
    48             printf("%lld
    ",ans[k]);
    49         }
    50     }
    51     return 0;
    52 }
    View Code
  • 相关阅读:
    刷皇室成员
    python 2.7中matplotlib的所有版本
    Linux命令使用时路径存在空格、特殊符号
    路径名太长导致无法读取文件
    谷歌浏览器打包插件
    Upload 上载新生
    Linux的终端(base),进入base环境
    Ubuntu16.04系统语言设置为中文以及搜狗输入法的安装
    R语言3D图导出矢量图有bug
    将本地文件复制到hadoop文件系统
  • 原文地址:https://www.cnblogs.com/Onlymyheart/p/11366406.html
Copyright © 2011-2022 走看看