#3498. 无限剑制(ubw)

I am the bone of my sword.

体は剣で出来ている.

Steel is my body, and fire is my blood.

血潮は鉄で 心は硝子.

I have created over a thousand blades.

几たびの戦场を越えて不败.

Unknown to Death.

ただの一度も败走はなく.

Nor known to Life.

ただの一度も理解されない.

Have withstood pain to create many weapons.

彼の者は常に独り 剣の丘で胜利に酔う.

Yet, those hands will never hold anything.

故に、生涯に意味はなく.

So as I pray, Unlimited Blade Works.

その体は、きっと剣で出来ていた.

“无限剑制”

等级:E~A++

种类:??

Unlimited Blade Works。

被称为固有结界的特殊魔术。

在一定时间内,将现实改写为心象世界,至今为止术者见过并能够认知的武器、在这个地方使用过的武器都能瞬间复制、保存。

但是,复制的武器等级会下降一级。

Emiya打算增加自己固有结界内的武器数量。他初始有 5 5 把武器,编号为 1-5 1−5 ,每把武器有 n(n \le 10^5) n(n≤10
5
) 个属性数值 v_i v
i

。Emiya接着制作 m m 把新武器,第 i i 次会选择编号为 a_i,b_i a
i

,b
i

的武器为模板投影出一把新的武器,新的武器的编号为 5+i 5+i ,每一个属性的值为两个模板武器对应属性的值的 max max 或 min min 。同时Emiya想知道新的武器的第 k_i k
i

个属性的数值。但是Emiya还要去做饭,所以需要他的master你来回答这些问题。
输入格式
第 1 1 行两个正整数 n,m n,m 。

第 2 2 到 6 6 行,每行 n n 个正整数,第 i i 个数表示 v_i v
i

第 7 7 到 6+m 6+m 行,每行 4 4 个数 p_i,a_i,b_i,k_i p
i

,a
i

,b
i

,k
i

,其中模板武器为 a_i,b_i a
i

,b
i

, p_i=0 p
i

=0 为 min min , p_i=1 p
i

=1 为 max max ,查询第 k_i k
i

个属性的数值。
输出格式
m m 行,每行 1 1 个整数,表示第 k_i k
i

个属性的数值
样例
样例输入

6 3
1 5 9 3 8 6
4 1 1 4 9 3
8 7 7 8 10 8
9 8 6 9 3 4
5 3 4 1 1 2
0 2 5 6
0 4 3 6
1 7 4 1
样例输出

2
4
9
数据范围与提示
保证对于每一个属性,初始 5 5 把武器该属性的数值不同。

10 % 10% : n \le 10^3,m \le 10^3 n≤10
3
,m≤10
3

另外 20 % 20% : m \le 5 \times 10^3 m≤5×10
3

另外 20 % 20% : a_i \le 5,b_i a
i

≤5,b
i

随机生成

另外 20 % 20% :所有 v_i v
i

值域在 [1,5] [1,5]

100 % 100% : k_i \le n \le 10^5,m \le 10^5,a_i,b_i \le 4+i,v_i \le 10^9 k
i

≤n≤10
5
,m≤10
5
,a
i

,b
i

≤4+i,v
i

≤10
9

来源
robinliu
题解:
可以注意到,对于前五个数相对大小关系相等的两列,对于新制的任意一件武器,传值的操作在同一列相对大小关系上是一样的。
所以可以用哈希值来表示相对大小关系相等的一类列。
修改(传值)时修改哈希值就可以了。
O(120*n);

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define N 100005
using namespace std;
struct node
{
    int p,s,v;
}cw[N][5];
int n,m,temp,ord[N],w[125][N+7],h[10005],to[N];
bool cmp(int x,int y){return cw[temp][x].v<cw[temp][y].v;}
int main()
{
	cin>>n>>m;
	for(int i=1;i<6;++i){
	    for(int j=1;j<=n;++j){
		    cin>>cw[j][i].v;
		}
	}int s=0,cnt=0;
	for(int i=1;i<=n;++i){
		temp=i;for(int j=1;j<6;++j)ord[j]=j;
		sort(ord+1,ord+6,cmp);
		for(int j=1;j<6;++j)cw[i][ord[j]].s=j;
		s=0;
		for(int j=1;j<6;++j)s=s*6+cw[i][j].s;
		for(int j=1;j<6;++j)cw[i][j].p=cw[i][ord[j]].v;
       // for(int j=1;j<6;++j)cw[i][cw[i][j].s].p=cw[i][j].v;
		if(!h[s]){
			h[s]=to[i]=++cnt;
			for(int j=1;j<6;++j)w[to[i]][j]=cw[i][j].s;
		}else to[i]=h[s];
		
	}
	for(int i=1+5,p,a,b,k;i<m+6;++i){
		scanf("%d%d%d%d",&p,&a,&b,&k);
		if(!p)w[to[k]][i]=min(w[to[k]][a],w[to[k]][b]);
		else w[to[k]][i]=max(w[to[k]][a],w[to[k]][b]);
		printf("%d\n",cw[k][w[to[k]][i]].p);
		for(int j=1;j<=cnt;++j){
			if(!p)w[j][i]=min(w[j][a],w[j][b]);
			else w[j][i]=max(w[j][a],w[j][b]);
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值