疏远度

题目描述

有 n 个人,每个人有k个属性值。 定义两个人的疏远度为他们k个属性值的差的绝对值的和。 形式化的说,用 ai,j 表示第i个人的第j个属性值( 1 ≤ i ≤ n,1 ≤ j ≤ k ), 则x和y的疏远度= 。 一开始n个人互不认识,现在有两种事件: 1 x y 表示x和y相互认识了。注意,认识具有传递性,即若a认识b,b认识c,则a认识c。 2 x 表示询问在x和x认识的人当中选出2个人(可以是同一个人),疏远度的最大值。 请你回答每个询问事件。

输入描述:

第一行三个整数n,k,m,分别表示人数,属性个数,事件个数。接下来n行,每行k个整数,第i行第j个数表示 ai,j 。接下来m行,每行描述一个事件,格式见题目描述。

输出描述:

对每个询问事件,输出一行表示答案。

示例1

输入

3 1 5
1
2
4
2 1
1 1 2
2 1
1 2 3
2 1

输出

0
1
3

说明

一开始1,2,3互不认识。第一个事件,询问1,这时要在{1}中选两个人,只能选1和1,疏远度=0。第二个事件,1和2互相认识了。第三个事件,询问1,这时要在{1,2}中选两个人,选出1和2,取得疏远度最大值=|1-2|=1。第四个事件,2和3互相认识了。第五个事件,询问1,这时要在{1,2,3}中选两个人,选出1和3,取得疏远度最大值=|1-4|=3。

备注:

全部的输入数据满足: 1 ≤ n ≤ 105 1 ≤ k ≤ 5 1 ≤ m ≤ 106 1 ≤ ai,j ≤ 109 1 ≤ x,y ≤ n
对于10%的数据,n ≤ 10,m ≤ 10
对于另外10%的数据,n ≤ 1000,m ≤ 1000
对于另外10%的数据,k=1
对于另外20%的数据,k=2
对于另外20%的数据,ai,j ≤ 2

这道题看到认识这两个字能想到并查集。
把他们都变成强连通快然后在根据题目中给的求和公式算出疏远值
在合并S,T的时候新的最大值要么是原来的答案要么是在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
typedef long long LL;
LL a[N][10],b[N][1<<5],ans=-9999999;
int c[N];
int kk;
int n,k,m;
LL max1(LL x,LL y)
{
 if(x<y)
  return y;
 else
  return x;
}
int find(int x)
{
 if(x==c[x]) 
  return x;
 c[x]=find(c[x]);
 return c[x];
}
int join(int x,int y)
{
 int x1=find(x);
 int y1=find(y);
 if(x1==y1) 
  return 0;
 c[y1]=x1;
 for(int i=0;i<=kk;i++)
 {
  b[x1][i]=max1(b[x1][i],b[y1][i]);
 }
 return 0;
}
int main()
{
 int p1,p2,p3;
 scanf("%d%d%d",&n,&k,&m);
 kk=(1<<k)-1;
 for(int i=1;i<=n;i++)
  for(int j=1;j<=k;j++)
   scanf("%lld",&a[i][j]);
 for(int i=1;i<=n;i++)
  for(int j=0;j<=kk;j++)
   for(int p=0;p<k;p++)
   {
    if(j&(1<<p))
     b[i][j]+=a[i][p+1];
    else
     b[i][j]-=a[i][p+1];
   }
 for(int i=1;i<=n;i++) 
  c[i]=i;
 for(int i=1;i<=m;i++)
 {
  scanf("%d",&p1);
  if(p1==1)
  {
   scanf("%d%d",&p2,&p3);
   join(p2,p3);
  }
  if(p1==2)
  {  
   ans=-999999999;
   scanf("%d",&p2);
   int tp=find(p2);
   for(int j=0;j<=kk;j++)
    ans=max1(ans,b[tp][j]+b[tp][j^kk]);
   printf("%lld\n",ans);
  }
 }
 return 0;
}

来源:nkw

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值