Codeforces 1093G题解(线段树维护k维空间最大曼哈顿距离)

题意是,给出n个k维空间下的点,然后q次操作,每次操作要么修改其中一个点的坐标,要么查询下标为[l,r]区间中所有点中两点的最大曼哈顿距离。

思路:参考blog:https://blog.csdn.net/Anxdada/article/details/81980574,里面讲了k维空间中的最大曼哈顿距离求法,然后利用这个方案改一改,用线段树来维护这些值就好了。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define mem(x) memset(x,0,sizeof x)
  5 #define lson o*2
  6 #define rson o*2+1
  7 #define m (l+r)/2
  8 const int maxn=200005;
  9 struct node
 10 {
 11     int mi,mx;
 12 }tr[4*maxn][35];
 13 void pushup(int o,int idx)
 14 {
 15     tr[o][idx].mi=min(tr[lson][idx].mi,tr[rson][idx].mi);
 16     tr[o][idx].mx=max(tr[lson][idx].mx,tr[rson][idx].mx);
 17 }
 18 int tmp[maxn][35];
 19 int a[maxn][35];
 20 void build(int o,int l,int r,int idx);
 21 void update(int o,int l,int r,int x,int idx);
 22 int cal(int n,int k)
 23 {
 24     int ans = 0, mi, mx, t;
 25     for (int s = 0 ; s < (1<<k) ; s ++)
 26     {
 27         mi = 1e9, mx = -1e9;
 28         for (int i = 1 ; i <= n ; i++)
 29         {
 30             t = a[i][0];
 31             for (int j = 1 ; j < k ; j++)
 32             {
 33                 if ((1<<j) & s) t += a[i][j];
 34                 else t -= a[i][j];
 35             }
 36             mi = min(mi, t);
 37             mx = max(mx, t);
 38             tmp[i][s]=t;
 39         }
 40         build(1,1,n,s);
 41         ans = max(ans, mx-mi);
 42     }
 43     return ans;
 44 }
 45 int cal2(int x,int n,int k)
 46 {
 47     int t;
 48     for (int s = 0 ; s < (1<<k) ; s ++)
 49     {
 50         int i=x;
 51         t = a[i][0];
 52         for (int j = 1 ; j < k ; j++)
 53         {
 54             if ((1<<j) & s) t += a[i][j];
 55             else t -= a[i][j];
 56         }
 57         tmp[i][s]=t;
 58         update(1,1,n,i,s);
 59     }
 60 }
 61 void build(int o,int l,int r,int idx)
 62 {
 63     if(l==r)
 64     {
 65         tr[o][idx].mi=tr[o][idx].mx=tmp[l][idx];
 66         return;
 67     }
 68     build(lson,l,m,idx);
 69     build(rson,m+1,r,idx);
 70     pushup(o,idx);
 71 }
 72 void update(int o,int l,int r,int x,int idx)
 73 {
 74     if(l==r)
 75     {
 76         tr[o][idx].mi=tr[o][idx].mx=tmp[l][idx];
 77         return;
 78     }
 79     if(x<=m) update(lson,l,m,x,idx);
 80     else update(rson,m+1,r,x,idx);
 81     pushup(o,idx);
 82 }
 83 int query(int o,int l,int r,int ql,int qr,int mark,int idx)
 84 {
 85     if(ql<=l&&qr>=r)
 86     {
 87         if(mark==1)
 88             return tr[o][idx].mi;
 89         else
 90             return tr[o][idx].mx;
 91     }
 92     if(qr<=m)
 93         return query(lson,l,m,ql,qr,mark,idx);
 94     if(ql>m)
 95         return query(rson,m+1,r,ql,qr,mark,idx);
 96     if(mark==1)
 97         return min(query(lson,l,m,ql,qr,mark,idx),query(rson,m+1,r,ql,qr,mark,idx));
 98     else
 99         return max(query(lson,l,m,ql,qr,mark,idx),query(rson,m+1,r,ql,qr,mark,idx));
100 }
101 int main()
102 {
103     int n,k;
104     scanf("%d%d",&n,&k);
105     for(int i=1;i<=n;i++)
106         for(int j=0;j<k;j++)
107             scanf("%d",&a[i][j]);
108     cal(n,k);
109     int q;
110     scanf("%d",&q);
111     while(q--)
112     {
113         int op;
114         scanf("%d",&op);
115         if(op==1)
116         {
117             int x;
118             scanf("%d",&x);
119             for(int i=0;i<k;i++)
120                 scanf("%d",&a[x][i]);
121             cal2(x,n,k);
122         }
123         else
124         {
125             int l,r;
126             scanf("%d%d",&l,&r);
127             int ans=0;
128             for (int s = 0 ; s < (1<<k) ; s ++)
129             {
130                 int mi=1e9;
131                 int mx=-1e9;
132                 mi=min(mi,query(1,1,n,l,r,1,s));
133                 mx=max(mx,query(1,1,n,l,r,2,s));
134                 ans=max(ans,mx-mi);
135             }
136             printf("%d\n",ans);
137         }
138     }
139 }
View Code

猜你喜欢

转载自www.cnblogs.com/iamamori/p/10126721.html