【noi.ac #2017】T2

题目

题目描述
小 D 在玩一款角色扮演游戏,通过前期的打怪,他现在得到了 kk 个不同的装备。

众所周知,角色扮演游戏中常常有复杂的人物属性,在这款游戏中,小 D 一共有 nn 种不同的属性,而每件装备都会都对这 nn 种属性有不同buff效果。

今天,小 D 走到一家铁匠铺里去合成装备。他每次可以将两个装备合成一个标号为 m+1m+1(mm 为当前装备个数)的新装备(原来的两个装备不会消失),但是由于小 D 锻造技术不高,所以合成有可能成功也有可能失败。如果合成成功,他会得到一个新装备,而新装备的各项属性的buff是两个装备对应属性的maxmax,而如果合成失败,他会得到一个新装备,新装备的各项属性的buff是两个装备对应属性的minmin。

现在小 D 现在有 qq 个操作,每次操作如下:

11 xx yy : 表示小 D 将第 xx 和第 yy 个装备合成了,并且合成成功。

22 xx yy : 表示小 D 将第 xx 和第 yy 个装备合成了,并且合成失败。

33 xx yy : 小 D 想知道第 xx 装备的第 yy 项属性的buff是多少。

输入格式
第一行三个整数 n,k,qn,k,q。

接下来 kk 行,每行 nn 个整数 aijaij,表示初始第 ii 件物品的第 jj 种属性的buff。

接下来 qq 行,每行三个整数描述一个操作。

输出格式
对于每一个 33 操作,输出一行一个整数表示答案。

样例输入
3 3 7
1 6 9
3 5 1
8 7 2
1 1 2
2 4 3
2 5 1
1 6 6
3 5 2
3 4 3
3 7 1
样例输出
6
9
1
数据范围
对于 20%20% 的数据,满足 n≤100n≤100。

对于另外 20%20% 的数据,合成不会失败(即没有 22 操作)。

对于 100%100% 的数据,满足 1≤n,q≤105,k≤12,1≤aij≤1091≤n,q≤105,k≤12,1≤aij≤109。

思路

考虑每一件装备维护一个集合S,里面的元素是A,A是一个2k的状态

那么对于每一个装备的属性满足
在这里插入图片描述

不难发现,如果两个装备取max,就是两个装备的并集,反之取min就是两个装备的交集,用bitset轻松解决
查询时只需要按照属性枚举bitset里面的状态就行了

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+77;
int n,k,q,a[15][N],yjy;
bitset<8192> f[N];
int main() 
{
	scanf("%d%d%d",&n,&k,&q);
	for(int i=1; i<=k; i++) for(int j=1; j<=n; j++) scanf("%d",&a[i][j]);
	for(int i=1; i<=k; i++) for(int j=0; j<(1<<k); j++) f[i][j]=(j>>(i-1)&1);
	yjy=k;
	while(q--) 
	{
		int op,x,y;
		scanf("%d%d%d",&op,&x,&y);
		if(op==1) f[++yjy]=f[x]|f[y];
		else if(op==2) f[++yjy]=f[x]&f[y];
		else 
		{
			int ans=0;
			for(int i=1; i<=k; i++) 
			{
				int s=0;
				for(int j=1; j<=k; j++) if(a[j][y]>=a[i][y]) s|=1<<(j-1);
				if(f[x][s]) ans=max(ans,a[i][y]);
			}
			printf("%d\n",ans);
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值