题解 石子合并

传送门

并不会做

发现两个异号数字相减的结果的绝对值等于这两个数字的绝对值之和
于是只要集合中有异号元素,就总可以构造出一种顺序使结果为所有元素的绝对值之和
然后考虑没有异号元素的情况
那就得找一对相邻元素相减一下形成一个异号元素
这个找结果绝对值最大的即可
复杂度 \(O(n)\)

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 2000010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;
int s[N];

namespace force{
	int dp1[2010][2010], dp2[2010][2010];
	void solve() {
		memset(dp1, 128, sizeof(dp1));
		memset(dp2, 127, sizeof(dp2));
		for (int i=1; i<=n; ++i) dp1[i][i]=dp2[i][i]=s[i];
		for (int len=2; len<=n; ++len) {
			for (int i=len; i<=n; ++i) {
				for (int j=i-len+2; j<=i; ++j) {
					dp1[i-len+1][i]=max(dp1[i-len+1][i], max(dp1[i-len+1][j-1]-dp2[j][i], dp1[j][i]-dp2[i-len+1][j-1]));
					dp2[i-len+1][i]=min(dp2[i-len+1][i], min(dp2[i-len+1][j-1]-dp1[j][i], dp2[j][i]-dp1[i-len+1][j-1]));
				}
			}
		}
		printf("%d\n", dp1[1][n]);
	}
}

namespace task1{
	int dp[2][2], now;
	void solve() {
		memset(dp, 0, sizeof(dp)); now=0;
		dp[now^1][0]=dp[now^1][1]=s[1];
		for (int i=2; i<=n; ++i,now^=1) {
			dp[now][0]=max( max(s[i]-dp[now^1][0], s[i]-dp[now^1][1]), max(dp[now^1][0]-s[i], dp[now^1][1]-s[i]) );
			dp[now][1]=min( min(s[i]-dp[now^1][0], s[i]-dp[now^1][1]), min(dp[now^1][0]-s[i], dp[now^1][1]-s[i]) );
		}
		printf("%d\n", max(dp[now^1][0], dp[now^1][1]));
	}
}

namespace task{
	void solve() {
		int minn=INF, ans=0;
		if (n==1) {printf("%d\n", s[1]); return ;}
		for (int i=2; i<=n; ++i) if (s[i-1]*s[i]<=0) goto jump;
		for (int i=2; i<=n; ++i) minn=min(minn, abs(abs(s[i])+abs(s[i-1])-abs(s[i]-s[i-1])));
		for (int i=2; i<=n; ++i) if (abs(abs(s[i])+abs(s[i-1])-abs(s[i]-s[i-1]))==minn) {
			s[i-1]=abs(s[i]-s[i-1]);
			for (int j=i; j<n; ++j) s[j]=s[j+1];
			--n;
			break;
		}
		// cout<<"s: "; for (int i=1; i<=n; ++i) cout<<s[i]<<' '; cout<<endl;
		jump: ;
		for (int i=1; i<=n; ++i) ans+=abs(s[i]);
		printf("%d\n", ans);
	}
}

signed main()
{
	freopen("stone.in", "r", stdin);
	freopen("stone.out", "w", stdout);

	int T=read();
	while (T--) {
		n=read();
		for (int i=1; i<=n; ++i) s[i]=read();
		// force::solve();
		task::solve();
	}
	
	return 0;
}
posted @ 2021-11-07 16:43  Administrator-09  阅读(0)  评论(0编辑  收藏  举报