栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

D - Concatenate Subsequences

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

D - Concatenate Subsequences

传送门:

https://atcoder.jp/contests/arc134/tasks/arc134_d

题意:给你一个长为2n的序列,可以在前n个数字中选出一条子序列,然后会附带给你i+n的后一半子序列(比如n为4,选了a1+a2+a4,那么会附带给你a5+a6+a8,最终序列就是a1+a2+a4+a5+a6+a8),要求该序列字典序最小。

分析:细节题。显然可以不断地在[l=1,r=n]的区间中贪心的找到最小数字后更新l,那么第一次会得到a1+a5(第一小的数字子序列a1 和 对应的子序列a5),这里要判断a5中的最小值是否小于等于a1的值。之后选择a2+a6,这里要根据a2的值与后一半被动加入的序列大小 判断a2能否加入。因为要用到每个值对应的位置,故先离散化。因为要多次查询区间最值,故预处理st表。

代码:

#include
using namespace std;
#define int long long
const int maxn=2e5;
const int maxlog=20;
int a[maxn];
int aa[maxn];
int b[maxn];
vectorv[maxn];
int ansp[maxn];
int table[maxn][maxlog];
int n;
sets[maxn];
map,int>mp;
int cntt;

void pre()
{
	memcpy(aa,a,sizeof a);
	sort(aa+1,aa+2*n+1);
	int cnt=unique(aa+1,aa+2*n+1)-aa-1;
	for(int i=1;i<=2*n;i++)
	{
        b[i]=lower_bound(aa+1,aa+cnt+1,a[i])-aa;
        table[i][0]=b[i];
	}
	for(int st=1;(1<>n;
	for(int i=1;i<=2*n;i++)
	{
		cin>>a[i];
	}
	pre();
	int l=1,r=n;
	while(1)
	{
		if(l>r) break;
		int st=__lg(r-l+1);
		int x=min(table[l][st],table[r-(1<=l)
				{
					ansp[++cntt]=v[x][i];
				}
			}
		}
		l=v[x][v[x].size()-1]+1;
	}
	for(int i=1;i<=cntt;i++)
	{
		cout<

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/722891.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号