• CF1093G [Multidimensional Queries]


    题意

    给出n(n<=2E5)个k(k<=5)维空间中的点,每次询问[l,r]中两个点曼哈顿距离的最大值(可以类比二维)


    思考

    根据初中数学,我们知道

    而每个维度上的曼哈顿距离是独立的。

    k又很小,因此我们可以一股脑地分类讨论,把所有可能的结果算出来。

    设f[S]表示k位二进制下k个维度的正负情况,如k=3时,(2,3,3)对应S(2)=110的结果为2+2-3。

    每次枚举S的所有情况,一股脑塞进去就行了!最后的结果就是max{f[i]+f[2^k-i-1]}。

    为什么是对的?因为这求的是最大值,所有可能的情况中电脑会机械化地算出最大可能的结果。

    简单线段树维护。


    代码

     1 #include<bits/stdc++.h> 
     2 using namespace std;
     3 const int maxn=2E5+5;
     4 int n,k,m,a[maxn][6];
     5 struct tree{int l,r,f[32];}t[maxn*4];
     6 tree merge(tree x,tree y)
     7 {
     8     tree z;
     9     z.l=x.l,z.r=y.r;
    10     for(int i=0;i<(1<<k);++i)z.f[i]=max(x.f[i],y.f[i]);
    11     return z;
    12 }
    13 void get(int x,int num)
    14 {
    15     for(int i=0;i<(1<<k);++i)
    16     {
    17         int sum=0;
    18         for(int j=0;j<k;++j)
    19         {
    20             if(i&(1<<j))sum+=a[x][j];
    21             else sum-=a[x][j];
    22         }
    23         t[num].f[i]=sum;
    24     }
    25 }
    26 void build(int l,int r,int num)
    27 {
    28     t[num].l=l;t[num].r=r;
    29     if(l==r)
    30     {
    31         get(l,num);
    32         return;
    33     }
    34     int mid=(l+r)>>1;
    35     build(l,mid,num*2);build(mid+1,r,num*2+1);
    36     t[num]=merge(t[num*2],t[num*2+1]);
    37 }
    38 void change(int pos,int num)
    39 {
    40     if(t[num].l==t[num].r)
    41     {
    42         get(pos,num);
    43         return;
    44     }
    45     int mid=(t[num].l+t[num].r)>>1;
    46     if(pos<=mid)change(pos,num*2);
    47     else change(pos,num*2+1);
    48     t[num]=merge(t[num*2],t[num*2+1]);
    49 }
    50 tree ask(int L,int R,int num)
    51 {
    52     if(L<=t[num].l&&t[num].r<=R)return t[num];
    53     int mid=(t[num].l+t[num].r)>>1;
    54     if(R<=mid)return ask(L,R,num*2);
    55     else if(mid<L)return ask(L,R,num*2+1);
    56     else return merge(ask(L,R,num*2),ask(L,R,num*2+1));
    57 }
    58 int main()
    59 {
    60     ios::sync_with_stdio(false);
    61     cin>>n>>k;
    62     for(int i=1;i<=n;++i)
    63         for(int j=0;j<k;++j)cin>>a[i][j];
    64     cin>>m;
    65     build(1,n,1);
    66     while(m--)
    67     {
    68         int opt,x;
    69         cin>>opt;
    70         if(opt==1)
    71         {
    72             cin>>x;
    73             for(int j=0;j<k;++j)cin>>a[x][j];
    74             change(x,1);
    75         }
    76         else
    77         {
    78             int l,r,ans=0;
    79             cin>>l>>r;
    80             tree u=ask(l,r,1);
    81             for(int i=0;i<(1<<k);++i)ans=max(ans,u.f[i]+u.f[(1<<k)-i-1]);
    82             cout<<ans<<endl;
    83         }
    84     }
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    博客园停更...
    Linux-常用命令汇总
    Linux-目录结构
    Mysql-python连接操作数据库
    Mysql-概念及常用命令
    Mysql-Sql查询汇总
    Mysql-Sql增删改查
    Mysql-Navicat破解使用
    Mysql-环境配置及问题解决
    Fiddler-AutoResponder替换资源
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/10554772.html
Copyright © 2020-2023  润新知