可以发现,装备的合成是一个树形结构
对于一次合成,新建一个点表示这两个装备合成后的装备,成为这两个装备的父亲(一定要新建因为要兹瓷询问某个装备被合成前的属性)
然后某个装备的某个属性就相当于问这个装备的子树中某个属性的最大值,线段树在dfs序上查找就行了,因为属性数不多,对每种属性开一棵线段树
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9
using namespace std;
inline void read(int &x)
{
char c;
while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
inline int _max(const int &x,const int &y){return x>y?x:y;}
const int maxn = 3100;
const int maxm = 450;
const int maxq = 210000;
int n,m,q;
int s[maxn][maxm];
struct edge
{
int y,nex;
edge(){}
edge(const int &_y,const int &_nex){y=_y;nex=_nex;}
}a[maxn<<1]; int len,fir[maxn];
inline void ins(const int x,const int y){a[++len]=edge(y,fir[x]);fir[x]=len;}
int siz[maxn],fa[maxn],id[maxn],dfn,N;
int idx[maxn];
void dfs(const int x)
{
siz[x]=1; id[x]=++dfn; idx[dfn]=x;
for(int k=fir[x];k;k=a[k].nex)
{
const int y=a[k].y;
if(y!=fa[x])
{
fa[y]=x;
dfs(y);
siz[x]+=siz[y];
}
}
}
int seg[maxm][maxn<<2],loc,c,k,lx,rx;
void build_(const int x,const int l,const int r)
{
if(l==r) { seg[k][x]=s[idx[l]][k]; return ; }
int mid=l+r>>1,lc=x<<1,rc=lc|1;
build_(lc,l,mid); build_(rc,mid+1,r);
seg[k][x]=_max(seg[k][lc],seg[k][rc]);
}
void upd(const int x,const int l,const int r)
{
if(l==r) { seg[k][x]=c; return ; }
int mid=l+r>>1,lc=x<<1,rc=lc|1;
if(loc<=mid) upd(lc,l,mid);
else upd(rc,mid+1,r);
seg[k][x]=_max(seg[k][lc],seg[k][rc]);
}
int query(const int x,const int l,const int r)
{
if(r<lx||rx<l) return 0;
if(lx<=l&&r<=rx) return seg[k][x];
int mid=l+r>>1,lc=x<<1,rc=lc|1;
return _max(query(lc,l,mid),query(rc,mid+1,r));
}
int nowi[maxn];
bool live[maxn];
struct qu
{
int k,a,b,c;
}b[maxq];
int main()
{
read(n); read(m); read(q); N=n;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) read(s[i][j]);
for(int i=1;i<=n;i++) nowi[i]=i,live[i]=true;
for(int i=1;i<=q;i++)
{
int x,y;
read(b[i].k); read(x); read(y); read(b[i].c);
b[i].a=x; b[i].b=y;
if(b[i].k==1)
{
ins(++N,nowi[x]); ins(nowi[x],N);
ins(N,nowi[y]); ins(nowi[y],N);
nowi[y]=N;
live[x]=false;
}
}
N++;
for(int i=1;i<=n;i++) if(live[i]) ins(N,nowi[i]);
dfn=0; dfs(N);
for(int i=1;i<=m;i++) k=i,build_(1,1,dfn);
for(int i=1;i<=n;i++) nowi[i]=i;
for(int i=1;i<=q;i++)
{
int x=nowi[b[i].a],y=b[i].b;
if(b[i].k==1) nowi[y]=fa[nowi[y]];
if(b[i].k==2) k=y,lx=id[x],rx=lx+siz[x]-1,printf("%d\n",query(1,1,dfn));
if(b[i].k==3) k=b[i].b,loc=id[b[i].a],c=b[i].c,upd(1,1,dfn);
}
return 0;
}