题解: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;
}

浙公网安备 33010602011771号