【题解】AT3944 [ARC092C] Both Sides Merger

时间:2022-05-14
本文章向大家介绍【题解】AT3944 [ARC092C] Both Sides Merger,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Sol

首先,答案肯定是原序列的一个子序列之和。
然后观察这个合并操作,很容易发现奇数位置只能与奇数位置合并,偶数位置只能与偶数位置合并。
那么问题转化为要在奇数位置上选一些数或者偶数位置上选一些数使他们和最大。
直接 dp 就行。
构造方案的话先删两端的,然后每次取中点一个一个合并即可。
时间复杂度 \(O(n^2)\)

Code

//LYC_music yyds!
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0)
#define lowbit(x) (x&(-x))
#define int long long
using namespace std;
inline char gc()
{
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
int read()
{
	int pos=1,num=0;
	char ch=getchar();
	while (!isdigit(ch))
	{
		if (ch=='-') pos=-1;
		ch=getchar();
	}
	while (isdigit(ch))
	{
		num=num*10+(int)(ch-'0');
		ch=getchar();
	}
	return pos*num;
}
void write(int x)
{
	if (x<0)
	{
		putchar('-');
		write(-x);
		return;
	}
	if (x>=10) write(x/10);
	putchar(x%10+'0');
}
void writesp(int x)
{
	write(x);
	putchar(' ');
}
void writeln(int x)
{
	write(x);
	putchar('\n');
}
const int N=5e3+10;
vector<int> G,Ans;
int n,a[N],dp[N],pre[N],ans,now,ff;
signed main()
{
//	freopen("1.in","r",stdin);
//	freopen("1.out","w",stdout);
	n=read();
	for (int i=1;i<=n;i++)
	{
		a[i]=read();
		if (a[i]>0) ff=1;
	}
	if (!ff)
	{
		int j=1;
		for (int i=1;i<=n;i++)
			if (a[i]>a[j]) j=i;
		writeln(a[j]); writeln(n-1);
		for (int i=1;i<j;i++)
			writeln(1);
		for (int i=n;i>j;i--)
			writeln(i-j+1);
		return 0;
	}
	for (int i=1;i<=n;i++)
	{
		dp[i]=a[i];
		for (int j=i-2;j>=1;j-=2)
			if (dp[j]+a[i]>dp[i]) dp[i]=dp[j]+a[i],pre[i]=j;
	}
	for (int i=1;i<=n;i++)
		if (ans<dp[i]) ans=dp[i],now=i;
	writeln(ans);
	while (pre[now])
	{
		G.push_back(now);
		now=pre[now];
	}
	G.push_back(now);
	reverse(G.begin(),G.end());
	for (int i=1;i<G[0];i++)
		Ans.emplace_back(1);
	int tot=G[0]-1;
	for (int i=n;i>=G[G.size()-1]+1;i--)
		Ans.emplace_back(i-tot);
	for (int i=0;i<(int)G.size()-1;i++)
	{
		int X=G[i+1]-G[i]+1-1;
		if (G[i+1]-G[i]==2)
		{
			Ans.emplace_back(2);
			continue;
		}
		for (int j=G[i]+1;j<G[i+1]-1;j+=2)
			Ans.emplace_back(3);
		Ans.emplace_back(2);
		tot+=X;
	}
	writeln(Ans.size());
	for (auto x:Ans)
		writeln(x);
}





原文地址:https://www.cnblogs.com/dd-d/p/16269670.html