#include<bits/stdc++.h>
#define FOR(i,a,b) for (int i=(a),_b=(b);i<=_b;i=i+1)
#define FORD(i,b,a) for (int i=(b),_a=(a);i>=_a;i=i-1)
#define REP(i,n) for (int i=0,_n=(n);i<_n;i=i+1)
#define FORE(i,v) for (__typeof((v).begin()) i=(v).begin();i!=(v).end();i++)
#define ALL(v) (v).begin(),(v).end()
#define fi   first
#define se   second
#define MASK(i) (1LL<<(i))
#define BIT(x,i) (((x)>>(i))&1)
#define div   ___div
#define next   ___next
#define prev   ___prev
#define left   ___left
#define right   ___right
#define __builtin_popcount __builtin_popcountll
using namespace std;
template<class X,class Y>
    void minimize(X &x,const Y &y) {
        if (x>y) x=y;
    }
template<class X,class Y>
    void maximize(X &x,const Y &y) {
        if (x<y) x=y;
    }
template<class T>
    T Abs(const T &x) {
        return (x<0?-x:x);
    }
class DisjointSet {
	private:
	vector<int> label; //label[x] stores the root of x if x is not root, otherwise it stores -(size of x's set).
	public:
	DisjointSet(){}
	DisjointSet(int n) {
		label.assign(n+7,-1); //label should contains at least n+1 elements, as x is 1-indexed.
		//At first, each node is a seperate set of size 1.
	}
	int find(int x) { //find the root of set which contains x.
		if (label[x]<0) return (x); //x is root iff label[x] is negative.
		label[x]=find(label[x]);
		return (label[x]); //find the root of x by recursion.
	}
	bool join(int a,int b) { // join the sets which contains a and b. Return false iff a and b are already in the same set.
		int x=find(a);
		int y=find(b);
		if (x==y) return (false); //A set contains both a and b.
		if (label[x]>label[y]) swap(x,y); //label[x]>label[y] means size(x)<size(y).
		//We speed up the disjoint set by joinning the smaller set to the bigger set
		label[x]+=label[y];
		label[y]=x; //Update the label of x and y.
		return (true);
	}
	int getSize(int x) { //return the size of set which contains x.
		return (-label[find(x)]);
	}
};

/* Author: Van Hanh Pham - skyvn97 */

/** END OF TEMPLATE - ACTUAL SOLUTION COMES HERE **/

#define MAX   200200
#define ROW   0
#define COL   1

struct Item {
    int cost, pos, type;
    Item() {
        cost = pos = type = 0;
    }
    Item(int _cost, int _pos, int _type) {
        cost = _cost; pos = _pos; type = _type;
    }
    bool operator < (const Item &x) const {
        return cost < x.cost;
    }
};

int w, h, rowCost[MAX], colCost[MAX];

void init(void) {
    scanf("%d%d", &w, &h);
    FOR(i, 1, w) scanf("%d", &rowCost[i]);
    FOR(i, 1, h) scanf("%d", &colCost[i]);
}

void process(void) {
    vector<Item> items;
    FOR(i, 1, w) items.push_back(Item(rowCost[i], i, ROW));
    FOR(i, 1, h) items.push_back(Item(colCost[i], i, COL));
    sort(ALL(items));

    DisjointSet dsuRow(w + 1), dsuCol(h + 1);
    int numCompRow = w + 1;
    int numCompCol = h + 1;
    long long res = 0;
    FORE(it, items) {
        if (it->type == ROW) {
            if (!dsuRow.join(it->pos, it->pos + 1)) continue;
            numCompRow--;
            res += 1LL * it->cost * numCompCol;
         } else {
            if (!dsuCol.join(it->pos, it->pos + 1)) continue;
            numCompCol--;
            res += 1LL * it->cost * numCompRow;
         }
    }
    cout << res << endl;
}
int main(void) {
    init();
    process();
    return 0;
}


/*** LOOK AT MY CODE. MY CODE IS AMAZING :D ***/


Measured memory_bytes: 4212