优先队列。使用一个最大堆和最小堆即可。但是注意最大堆里删除掉的了,可能在最小堆里出现。所以需要保证每次弹出的在另一个堆里没有删掉。所以加两个数组判断这个地方。答案要用longlong。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 1000005
#define LIM 18446744073709551615
using namespace std;
int axp[MAXN],inp[MAXN];
int main()
{
int n;
while(scanf("%d",&n)&&n)
{
int k;
ll ans=0;
priority_queue<int,vector<int> > maxp;
priority_queue<int,vector<int>,greater<int> > minp;
memset(axp,0,sizeof(axp));
memset(inp,0,sizeof(inp));
for(int i=0; i<n; ++i)
{
scanf("%d",&k);
for(int j=0; j<k; ++j)
{
int t;
scanf("%d",&t);
maxp.push(t);
minp.push(t);
}
int a=0,b=0;
while(axp[maxp.top()])
{
axp[maxp.top()]--;
maxp.pop();
}
a=maxp.top();
maxp.pop();
inp[a]++;
while(inp[minp.top()])
{
inp[minp.top()]--;
minp.pop();
}
b=minp.top();
minp.pop();
axp[b]++;
ans+=a-b;
}
printf("%lld\n",ans);
}
return 0;
}