题解:AT_arc196_a 删除邻项

先看看数据,可哀的 \(2 \le N \le 3 \times 10^5\),区间动规卡飞。

只能想其他方法了(废话)

手玩样例一,再多造几个 \(N\) 为偶数的样例,就会发现,我们把大的一半的那些数标记加号,小的一半标记减号,则永远有一个加号和一个减号挨一起(手玩样例一就可以发现),而要保证得分最大就是要保证大的数与小的数同时删除。

这是可能就有人要问了,但没法保证最大的数与最小的数在一起啊?

仔细想想,就能明白,比如 \(1, 5, 2, 3\),先删 \(1, 5\) 与先删 \(2, 3\) 是没有区别的。

偶数便想完了,再考虑奇数的情况。

无论怎么删,总要留一个数,\(2 \le N \le 3 \times 10^5\),足够我们枚举最后剩下的数,剩下的就只能 \(O(1)\)\(O(\log N)\) 了。

确定了剩下的数,剩下的就又是偶数的情况,但我们需要快速地知道大的一部分与小的一部分,这个不用多想,肯定对顶堆。

这就解决了。

代码:

# include <bits/stdc++.h>
using namespace std;
long long n ,  sum , sumx , sumy , maxn , a[300010] , l[300010] , r[300010];
priority_queue <long long> x;
priority_queue <long long , vector <long long> , greater <long long> > y;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for(int i = 1 ; i <= n ; i ++)
	{
		cin >> a[i];
	}
	if(n == 3)
	{
		cout << min(abs(a[1] - a[2]) , abs(a[2] - a[3]));
		return 0;
	}
	if(!(n % 2))
	{
		sort(a + 1 , a + n + 1);
		for(int i = 1 ; i <= n / 2 ; i ++)
		{
			sum += a[i + n / 2] - a[i];
		}
		cout << sum;
		return 0;
	}
    y.push(2e9);
    x.push(-2e9);
	for(int i = 2 ; i <= n ; i += 2)
	{
		if(x.empty())
		{
			x.push(a[i - 1]);
			sumx += a[i - 1];
		}
		else if(a[i] > x.top())
		{
			y.push(a[i - 1]);
			sumy += a[i - 1];
		}
		else
		{
			x.push(a[i - 1]);
			sumx += a[i - 1];
		}
		if(x.empty())
		{
			x.push(a[i]);
			sumx += a[i];
		}
		else if(a[i] > x.top())
		{
			y.push(a[i]);
			sumy += a[i];
		}
		else
		{
			x.push(a[i]);
			sumx += a[i];
		}
		if(x.size() > y.size())
		{
			y.push(x.top());
			sumy += x.top();
			sumx -= x.top();
			x.pop();
		}
		else
		{
			x.push(y.top());
			sumx += y.top();
			sumy -= y.top();
			y.pop();
		}
		l[i] = sumy - sumx;
	}
	priority_queue <long long> newx;
	priority_queue <long long , vector <long long> , greater <long long> > newy;
	sumx = sumy = 0;
	x = newx , y = newy;
    y.push(2e9);
    x.push(-2e9);
	for(int i = n - 1 ; i >= 1 ; i -= 2)
	{
		if(x.empty())
		{
			x.push(a[i]);
			sumx += a[i];
		}
		else if(a[i] > x.top())
		{
			y.push(a[i]);
			sumy += a[i];
		}
		else
		{
			x.push(a[i]);
			sumx += a[i];
		}
		if(x.empty())
		{
			x.push(a[i + 1]);
			sumx += a[i + 1];
		}
		else if(a[i] > x.top())
		{
			y.push(a[i + 1]);
			sumy += a[i + 1];
		}
		else
		{
			x.push(a[i + 1]);
			sumx += a[i + 1];
		}
		if(x.size() > y.size())
		{
			y.push(x.top());
			sumy += x.top();
			sumx -= x.top();
			x.pop();
		}
		else
		{
			x.push(y.top());
			sumx += y.top();
			sumy -= y.top();
			y.pop();
		}
		r[i] = sumy - sumx;
	}
	for(int i = 1 ; i <= n ; i += 2)
	{
		maxn = max(maxn , l[i - 1] + r[i + 1]);
	}
	cout << maxn;
	return 0;
}
posted @ 2025-06-23 16:18  zhangyimin12345  阅读(42)  评论(0)    收藏  举报