D. Divide and Sum

time limit per test2 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output

You are given an array a of length 2n. Consider a partition of array a into two subsequences p and q of length n each (each element of array a should be in exactly one subsequence: either in p or in q).

Let’s sort p in non-decreasing order, and q in non-increasing order, we can denote the sorted versions by x and y, respectively. Then the cost of a partition is defined as f(p,q)=∑ni=1|xi−yi|.

Find the sum of f(p,q) over all correct partitions of array a. Since the answer might be too big, print its remainder modulo 998244353.

Input
The first line contains a single integer n (1≤n≤150000).

The second line contains 2n integers a1,a2,…,a2n (1≤ai≤109) — elements of array a.

Output
Print one integer — the answer to the problem, modulo 998244353.

Examples
inputCopy
1
1 4
outputCopy
6
inputCopy
2
2 1 2 1
outputCopy
12
inputCopy
3
2 2 2 2 2 2
outputCopy
0
inputCopy
5
13 8 35 94 9284 34 54 69 123 846
outputCopy
2588544
Note
Two partitions of an array are considered different if the sets of indices of elements included in the subsequence p are different.

In the first example, there are two correct partitions of the array a:

p=[1], q=[4], then x=[1], y=[4], f(p,q)=|1−4|=3;
p=[4], q=[1], then x=[4], y=[1], f(p,q)=|4−1|=3.
In the second example, there are six valid partitions of the array a:

p=[2,1], q=[2,1] (elements with indices 1 and 2 in the original array are selected in the subsequence p);

p=[2,2], q=[1,1];

p=[2,1], q=[1,2] (elements with indices 1 and 4 are selected in the subsequence p);

p=[1,2], q=[2,1];

p=[1,1], q=[2,2];

p=[2,1], q=[2,1] (elements with indices 3 and 4 are selected in the subsequence p).

题意就是给出你一个长度为CF-D. Divide and Sum_#include的数组,然后让你分成CF-D. Divide and Sum_#define_02CF-D. Divide and Sum_i++_03这两个数组,p是单调不减,q是单调不增(注意这个条件解题的重点),然后给出个定义CF-D. Divide and Sum_i++_04

最后就是求这个式子的值,还有就是对998244353去膜,注意数据量是150000

思路:

首先看下这个式子CF-D. Divide and Sum_i++_04可以看出其实xi和yi对结果的影响就是,max(xi,yi)-min(xi,yi);也就是加上较大值,减去较小值。然后就是上面我们说的重点定义p是单调不减,q是单调不增看下图:

CF-D. Divide and Sum_i++_06


这个图就是构造出来CF-D. Divide and Sum_#define_02CF-D. Divide and Sum_i++_03然后对应的差,我们可以看出CF-D. Divide and Sum_i++_09对应的是CF-D. Divide and Sum_i++_10 ,CF-D. Divide and Sum_i++_11对应的是CF-D. Divide and Sum_#include。然后我们看出取较大值都是再原数列后CF-D. Divide and Sum_i++_11个数中找出来的,具体看这个例子吧:

CF-D. Divide and Sum_#include_14


CF-D. Divide and Sum_i++_15


第一个是我们对CF-D. Divide and Sum_#include排序后的数组,下一个是按CF-D. Divide and Sum_i++_17构造出来的数组,可以看出

  1. 1->8 对结果的影响+8-1
  2. 2->7 对结果的影响+7-2
  3. 3->6 对结果的影响+6-3
    可以看出这个结果就是 原数列排序后的后3个和减去前三个3.
    再看下面那个图我们将6和3交换(是把6放入p中,把3放入q中)然后再次按要求排序就得出那个图也就是
    1, 1->8 对结果的影响+8-1
    2, 2->7 对结果的影响+7-2
    3, 6->3 对结果的影响+6-3
    好像这个例子不够生动形象,那我们把6和2换一下
  4. CF-D. Divide and Sum_#define_18

  5. 这样就更形象了
  • 1->8 对结果的影响+8-1
  • 3->7 对结果的影响+7-3
  • 6->2 对结果的影响+6-2
    这样我们就可以看出其实每次换种顺序对结果并没有影响,所以我们就是找顺序的种数就行。种数就是从CF-D. Divide and Sum_i++_19中选出CF-D. Divide and Sum_i++_20个也就是CF-D. Divide and Sum_i++_21
    最后就化成CF-D. Divide and Sum_i++_22
#pragma
#pragma
#include <immintrin.h>
#pragma
#include <map>
#include <queue>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <math.h>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
typedef pair<ll,ll> pii;
#define
#define
#define
#define
#define
const int maxn=3e5+1010;
#define
#define
#define
const int mod=998244353;
const int MOD=10007;

inline int read() {
int x=0;
bool t=false;
char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}

/*
vector<ll> m1;
vector<ll> m2;
priority_queue<ll , vector<ll> , greater<ll> > mn;//上 小根堆 小到大
priority_queue<ll , vector<ll> , less<ll> > mx;//下 大根堆 大到小
map<ll,ll>mp;*/
int n;
ll a[maxn];
ll fac[maxn];
ll infac[maxn];
ll qpow(ll a,ll b){
ll sum=1;
while(b){
if(b&1) sum=sum*a%mod;
b>>=1;
a=a*a%mod;
}
return sum;
}
ll sum,ans;
#define
int main() {
scanf("%d",&n);
for(int i=1;i<=n*2;i++){
scanf("%lld",&a[i]);
}
infac[0]=fac[0]=1;
for(int i=1;i<=n*2;i++){
fac[i]=fac[i-1]*i%mod;
}
for(int i=1;i<=n;i++) infac[i]=1ll*infac[i-1]*qpow(i,mod-2)%mod;
sort(a+1,a+1+2*n);
for(int i=1;i<=n;i++) sum+=a[i];
for(int i=n+1;i<=2*n;i++) ans+=a[i];
ll res=1ll*(ans-sum+mod)%mod*fac[n*2]%mod*infac[n]%mod*infac[n]%mod;
printf("%lld\n",res);
return 0;
}