吐槽:连续三天的\(duliu\)题,第一题签到,后面???送命!!
T1.cuvelia
一句话题意:求对于每一个\(~i~(~i~\le~n)\),从一个序列中选出\(n\)个数,使得选出的数两两之差的绝对值最大。
应该挺简单的吧,我们如果把选出来的序列排个序,对于一个位置\(~p\),假如他右边有\(n\)个数,每一个数和它作差的贡献为\(a_R~-~a_p\),所以对于\(a_p\),它的贡献为\(-~n~\times~a_p\),同理,假如左边有\(m\)个数,那么这个数总共的贡献为\((m-n)~\times~a_p\)。又因越右边的数\(m~-~n\)越大,所以整个选择的序列为单调不下降,然后对于整个序列在中点右边的数\(m~-~n~\ge~0\),所以这些数越大越好,左边的数\(m~-~n~\le~0\),所以选择的数越小越好,因此整个选择的序列一定为原序列排序后的左右两边各\(i/2\)个。
大致算法就讲完了,然后用前缀和维护就好了。
手起码落,把这题咔嚓了:
#include<bits/stdc++.h>
#define re register
using namespace std;
const int N=300005;
int n,a[N];
long long ans[N][2],sum[N][2];
int main()
{
scanf("%d",&n);
for(re int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
for(re int i=1;i<=n;i++) sum[i][0]=sum[i-1][0]+a[i];
for(re int i=n;i>0;i--) sum[i][1]=sum[i+1][1]+a[i];
for(re int i=1;i<=(n>>1);i++)
{
ans[i<<1][0]=ans[(i<<1)-1][0]-sum[i][0];
ans[(i<<1)+1][0]=ans[i<<1][0]-sum[i][0];
}
re int mid=(n-1)/2+1;
for(re int i=n,l;i>mid;i--)
{
l=n-i+1;
ans[l<<1][1]=ans[(l<<1)-1][1]+sum[i][1];
ans[(l<<1)+1][1]=ans[l<<1][1]+sum[i][1];
}
for(re int i=1;i<=n;i++) printf("%lld\n",ans[i][0]+ans[i][1]);
return 0;
}
T2?T3?T4? 咕咕咕~~