CF1093G [Multidimensional Queries]

GreenDuck發表於2019-03-18

題意

給出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

 

相關文章