训练赛题解2

F - 最长上升子序列

你原本有一个 1 到 n 的排列,但是不慎地,你遗忘了它,但是你记得以 第i个位置 结尾的最长上升子序列的长度数组 {an} ,现在希望你能够构造一个符合条件的排列 p ,如果不存在符合上述条件的排列 p ,则输出  - 1。

这里定义以 第i位置 结尾的最长上升子序列的长度,为符合以下条件的整数数组 

 中 k 的最大值。

本题输入输出量比较大,请选手注意。

Input

第一行一个整数 n (1 ≤ n ≤ 106)

第二行 n 个整数表示数组 {an} (1 ≤ ai ≤ n),其中 ai 表示以 i 结尾的最长上升子序列的长度。

Output

一行 n 个整数表示排列 p ,如果无解,则输出  - 1。

Examples

InputcopyOutputcopy
5
1 2 2 3 3
1 5 2 4 3 
InputcopyOutputcopy
7
1 1 2 1 4 4 4
-1
思路:一个全排列问题,从最小的那个递增子序列长度开始排列,逆向构造dp,如果a[i]>s+1,则无解,输出-1。
#include<bits/stdc++.h>
using namespace std;
const int N=1e7+10;
int n,a[N],b[N],s=0;
int main()
{
	cin>>n;
	bool flag=true;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		b[a[i]]++;
		if(a[i]>s+1) flag=false;
		else if(a[i]>s)
		s=a[i];
	}
	if(!flag)
	cout<<"-1"<<endl;
	else
	{
		for(int i=1;i<N;i++)
		b[i]+=b[i-1];
		for(int i=1;i<=n;i++)
		a[i]=b[a[i]]--;
		for(int i=1;i<=n;i++)
		cout<<a[i]<<" ";
	}
	return 0;
}

L - 养成游戏

小塔最近在玩一款培育养成类游戏,她培育的角色有 n 个属性,每个属性 Ai 是 0 到 K 的一个整数。这个游戏的终极目标是在最后的展示大会上获得最高的评分,最后的展示大会上有一些评委,每个评委都有各自的评判标准,当你达成了这个评委的评判标准,你就能获得这个评委的评分,评委的评判标准格式如下,可以由一个整数七元组 

 表示。

当 op 为 0 时,代表培育的角色满足 a × Ai + b × Aj ≤ d 时就可以获得 v 的评分。

当 op 为 1 时,代表培育的角色满足 a × Ai + b × Aj ≥ d 时就可以获得 v 的评分。

由于评委们也不想让自己的评分规则太麻烦,所以这里的a, b满足 - 1 ≤ a, b ≤ 1。

如果小塔能控制她养成的角色的属性的值,现在她问你她最高能在展示大会上获得多少评分呢?

Input

第一行两个整数 n, m, k (2 ≤ n ≤ 6, 1 ≤ m ≤ 100, 1 ≤ K ≤ 8)。

接着有 m 行,每行有七个整数 i, j, op, a, b, d, v,表示一组评委的评判标准。其中每个参数的具体限制如下:

Output

输出一个整数代表她可以获得的最高评分

Examples

InputcopyOutputcopy
3 5 5
3 1 0 1 -1 0 4
3 1 0 1 1 2 2
3 1 0 1 0 1 3
3 2 1 1 1 2 0
3 2 1 1 -1 1 3
12
InputcopyOutputcopy
3 5 5
1 2 1 -1 0 0 0
3 2 1 0 -1 3 2
2 3 0 -1 -1 0 4
3 1 1 1 0 0 0
1 3 0 0 1 2 9
13

Note

在第一个样例里,小塔培养的角色属性为 A1 = 1, A2 = 0, A3 = 1 时,可以获得 12 分。

思路:由于数据范围并不大,可以直接枚举所有属性值的所有可能组合,取这些组合最终得分的最大值,用dfs递归求所有可能的组合情况
#include<bits/stdc++.h>
using namespace std;
int n,m,k,a[10],q[110][10];
int ans;
int check()
{
	int s=0,t;
	for(int i=1;i<=m;i++)
	{
		t=q[i][4]*a[q[i][1]]+q[i][5]*a[q[i][2]];
		if(!q[i][3])
		{
			if(t<=q[i][6])
			s+=q[i][7];
		}
		else
		{
			if(t>=q[i][6])
			s+=q[i][7];
		}
	}
	return s;
}
void dfs(int d)
{
	if(d>n)
	{
		ans=max(ans,check());
		return;
	}
	for(int i=0;i<=k;i++)
	{
		a[d]=i;
		dfs(d+1);
	}
}
int main()
{
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=7;j++)
		cin>>q[i][j];
	} 
	dfs(1);
	cout<<ans<<endl;
	return 0;
}

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值