P2501 [HAOI2006] 數字序列

kanade16發表於2024-09-22
#include <bits/stdc++.h>
using namespace std;
const int N = 35 * 1000 + 10;
int n;
int f[N],a[N];
vector <int> pre[N];
int dp[N];
long long ans[N];
int len[N];
int main()
{
	scanf("%d",&n);
	for(int i = 1;i <= n;i++)
		scanf("%d",&f[i]),a[i] = f[i] - i;
	dp[0] = 0;
	a[0] = -999999999;
	dp[1] = 1;
	pre[1].push_back(0);
	for(int i = 2;i <= n;i++)
	{
		//cout << i << endl;
		int maxans = 0,cnt = -1;
		for(int j = 0;j < i;j++)
		{
			if(a[j] <= a[i])
			{
				if(dp[j] > maxans)
				{
					maxans = dp[j];
					cnt = -1;
					pre[i].clear();
					pre[i].push_back(j);
				}
				else if(dp[j] == maxans)
				{
					pre[i].push_back(j);
				}
			}
		}
		dp[i] = maxans + 1;
		len[i] = pre[i].size() - 1;//len不是個數
	}
	int ans1 = -1;
	for(int i = 1;i <= n;i++)
		ans1 = max(ans1,dp[i]);
	printf("%d\n",n - ans1);
	for(int i = 1;i <= n;i++)
	{
		if(pre[i][0] == 0 && len[i] == 0)
		{
			for(int j = 1;j < i;j++)
			{
				ans[i] += (a[j] - a[i]);
			}
		}
		else
		{
			ans[i] = 1999999999;
			for(int j = 0;j <= len[i];j++)
			{
				int t = pre[i][j];
				long long temp = ans[t];
				long long min_plus = 1999999999;
				long long xh1 = 0,dh1 = 0;
				int dn1 = 0,xn1 = 0;
				int xn2 = 0,dn2 = 0;
				long long xh2 = 0,dh2 = 0;
				for(int g = t + 1;g < i;g++)
				{
					if(a[g] > a[i])dn2++,dh2 += a[g];
					else xn2++,xh2 += a[g];
				}
				for(int k = t;k < i;k++)
				{
					long long tans = dh2 - a[i] * dn2  + xn2 * a[i] - xh2;
					tans += dh1 - a[t] * dn1 + xn1 * a[t] - xh1;
					min_plus = min(min_plus,tans);
					if(a[k + 1] < a[t])
					{
						xn1 ++;
						xh1 += a[k + 1];
					}
					else
					{
						dn1 ++;
						dh1 += a[k + 1];
					}
					if(a[k + 1] < a[i])
					{
						xn2 --;
						xh1 -= a[k + 1];
					}
					else
					{
						dn2 --;
						dh1 -= a[k + 1];
					}
				}
				temp += min_plus;
				ans[i] = min(ans[i],temp);
			}
		}
	}
	long long minn = 1999999999;
	for(int i = 1;i <= n;i++)
	{
		if(dp[i] == ans1)
		{
			long long tt = ans[i];
			for(int j = i + 1;j <= n;j++)tt += a[i] - a[j];
			minn = min(minn,tt);
		}
	}
	printf("%lld\n",minn);
	return 0;
}

熬不住了,先睡覺了,明天再寫思路

相關文章