题目:[曼哈顿距离,线段树]Educational Codeforces Round 56G. Multidimensional Queries
原题链接:
http://codeforces.com/contest/1093/problem/G
题意:
给n个k维的点,q个询问,求曼哈顿距离最远的两个点的距离,操作是改点的坐标。
题解:
和poj2926是一样的,压缩下状态就好。
poj2926看这位大神的博客https://www.cnblogs.com/tanhehe/archive/2013/05/25/3099400.html
然后在线操作的话就维护下(1<
总结:
查询的时候分别查一次最大值和最小值,不要直接查询最大值和最小值的差,因为线段树维护的不是这个差,而是极值。
代码:
#define push_back pb
#define make_pair mk
#define rd read()
#define mem(a,b) memset(a,b,sizeof(a))
#define bug printf("*********\n");
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ls tr[u].ch[0]
#define rs tr[u].ch[1]
#define FIN freopen(D://code
#define debug(x) cout<<"["<
#define IO ios::sync_with_stdio(flse),cin.tie(0);
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using std::pair;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int maxn = 2e5 + 10;
const int maxm = 1e6 + 10;
const int mod = 998244353 ;
const int inf = 0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const double dinf=1e20;
const double eps=1e-8;
using namespace std;
ll read() {
ll X = 0, p = 1; char c = getchar();
for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
return X * p;
}
int n,dem;
int a[maxn][6];
int ma[maxn<<2][33],mi[maxn<<2][33];
void pushup(int rt)
{
for(int i=0;i<(1<<dem);i++)
{
ma[rt][i]=max(ma[rt<<1][i],ma[rt<<1|1][i]);
mi[rt][i]=min(mi[rt<<1][i],mi[rt<<1|1][i]);
}
}
void build(int l,int r,int rt)
{
if(l==r)
{
int sum=0;
for(int i=0;i<(1<<dem);i++)
{
ma[rt][i]=-inf;
mi[rt][i]=inf;
}
for(int i=0;i<(1<<dem);i++)
{
int sum=0;
for(int k=0;k<dem;k++)
{
if((i>>k)&1) sum+=a[l][k];
else sum-=a[l][k];
}
ma[rt][i]=max(ma[rt][i],sum);
mi[rt][i]=min(mi[rt][i],sum);
}
return ;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int p,int l,int r,int rt)
{
if(l==p&&r==p)
{
int sum=0;
for(int i=0;i<(1<<dem);i++)
{
ma[rt][i]=-inf;
mi[rt][i]=inf;
}
for(int i=0;i<(1<<dem);i++)
{
int sum=0;
for(int k=0;k<dem;k++)
{
if((i>>k)&1) sum+=a[l][k];
else sum-=a[l][k];
}
ma[rt][i]=max(ma[rt][i],sum);
mi[rt][i]=min(mi[rt][i],sum);
}
return ;
}
int mid=(l+r)>>1;
if(p<=mid) update(p,lson);
if(mid<p) update(p,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt,int i,int f)
{
if(L<=l&&r<=R)
{
if(f)return ma[rt][i];
else return mi[rt][i];
}
int mid=(l+r)>>1;
int ret;
if(f)
{
ret=-inf;
if(L<=mid) ret=max(ret,query(L,R,lson,i,f));
if(R>mid) ret=max(ret,query(L,R,rson,i,f));
}
else
{
ret=inf;
if(L<=mid) ret=min(ret,query(L,R,lson,i,f));
if(R>mid) ret=min(ret,query(L,R,rson,i,f));
}
return ret;
}
/*void dfs(int l,int r,int rt,int i)
{
if(l>r) return ;
if(l==r)
{
cout<<l<<" "<<r<<" "<<ma[rt][i]<<" "<<mi[rt][i]<<endl;
return;
}
int mid=(l+r)>>1;
dfs(lson,i);
cout<<l<<" "<<r<<" "<<ma[rt][i]<<" "<<mi[rt][i]<<endl;
dfs(rson,i);
}*/
int main()
{
cin>>n>>dem;
for(int i=1;i<=n;i++)
{
for(int j=0;j<dem;j++)
scanf("%d",&a[i][j]);
}
build(1,n,1);
int q;
cin>>q;
int op,l,r;
while(q--)
{
scanf("%d%d",&op,&l);
if(op==1)
{
for(int i=0;i<dem;i++) scanf("%d",&a[l][i]);
update(l,1,n,1);
}
else
{
scanf("%d",&r);
int ans=-inf;
for(int i=0;i<(1<<dem);i++)
{
ans=max(ans,query(l,r,1,n,1,i,1)-query(l,r,1,n,1,i,0));
}
printf("%d\n",ans);
}
}
}