diff --git a/applications/test/GAMGAgglomeration/Test-GAMGAgglomeration.C b/applications/test/GAMGAgglomeration/Test-GAMGAgglomeration.C
index cf5584e01ff4018c2166d66ef227c8a1912d1b3c..7c09aefb649a55fc88c4e372ac241106166f857f 100644
--- a/applications/test/GAMGAgglomeration/Test-GAMGAgglomeration.C
+++ b/applications/test/GAMGAgglomeration/Test-GAMGAgglomeration.C
@@ -70,7 +70,10 @@ int main(int argc, char *argv[])
     );
 
     labelList cellToCoarse(identity(mesh.nCells()));
-    labelListList coarseToCell(invertOneToMany(mesh.nCells(), cellToCoarse));
+    CompactListList<label> coarseToCell
+    (
+        invertOneToManyCompact(mesh.nCells(), cellToCoarse)
+    );
 
     ++runTime;
 
@@ -78,16 +81,11 @@ int main(int argc, char *argv[])
     {
         volScalarField scalarAgglomeration
         (
-            IOobject
-            (
-                "agglomeration",
-                runTime.timeName(),
-                mesh,
-                IOobject::NO_READ,
-                IOobject::AUTO_WRITE
-            ),
+            mesh.thisDb().newIOobject("agglomeration"),
             mesh,
-            dimensionedScalar(dimless, Zero)
+            Foam::zero{},
+            dimless,
+            fvPatchFieldBase::zeroGradientType()
         );
         scalarField& fld = scalarAgglomeration.primitiveFieldRef();
         forAll(fld, celli)
@@ -142,31 +140,23 @@ int main(int argc, char *argv[])
         }
 
 
-        forAll(addr, fineI)
+        forAll(addr, finei)
         {
-            const labelList& cellLabels = coarseToCell[fineI];
-            forAll(cellLabels, i)
-            {
-                cellToCoarse[cellLabels[i]] = addr[fineI];
-            }
+            labelUIndList(cellToCoarse, coarseToCell[finei]) = addr[finei];
         }
-        coarseToCell = invertOneToMany(coarseSize, cellToCoarse);
+        coarseToCell = invertOneToManyCompact(coarseSize, cellToCoarse);
 
         // Write agglomeration
         {
             volScalarField scalarAgglomeration
             (
-                IOobject
-                (
-                    "agglomeration",
-                    runTime.timeName(),
-                    mesh,
-                    IOobject::NO_READ,
-                    IOobject::AUTO_WRITE
-                ),
+                mesh.thisDb().newIOobject("agglomeration"),
                 mesh,
-                dimensionedScalar(dimless, Zero)
+                Foam::zero{},
+                dimless,
+                fvPatchFieldBase::zeroGradientType()
             );
+
             scalarField& fld = scalarAgglomeration.primitiveFieldRef();
             forAll(fld, celli)
             {
@@ -193,9 +183,9 @@ int main(int argc, char *argv[])
             }
 
             // Determine coarse cc
-            forAll(coarseToCell, coarseI)
+            forAll(coarseToCell, coarsei)
             {
-                const labelList& cellLabels = coarseToCell[coarseI];
+                const auto& cellLabels = coarseToCell[coarsei];
 
                 point coarseCc = average
                 (
@@ -204,10 +194,8 @@ int main(int argc, char *argv[])
                 meshTools::writeOBJ(str, coarseCc);
                 vertI++;
 
-                forAll(cellLabels, i)
+                for (label celli : cellLabels)
                 {
-                    label celli = cellLabels[i];
-
                     str << "l " << celli+1 << ' ' << vertI << nl;
                 }
             }
diff --git a/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C b/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C
index 384143a52d94664a35006c8e451941ff4152aa32..c5cdb17370790834e4d4bb19c0b4cbf4d92d94fa 100644
--- a/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C
+++ b/applications/utilities/mesh/manipulation/polyDualMesh/meshDualiser.C
@@ -65,16 +65,19 @@ void Foam::meshDualiser::checkPolyTopoChange(const polyTopoChange& meshMod)
 
     if (nUnique < points.size())
     {
-        labelListList newToOld(invertOneToMany(nUnique, oldToNew));
+        CompactListList<label> newToOld
+        (
+            invertOneToManyCompact(nUnique, oldToNew)
+        );
 
-        forAll(newToOld, newI)
+        forAll(newToOld, newi)
         {
-            if (newToOld[newI].size() != 1)
+            if (newToOld[newi].size() != 1)
             {
                 FatalErrorInFunction
-                    << "duplicate verts:" << newToOld[newI]
+                    << "duplicate verts:" << newToOld[newi]
                     << " coords:"
-                    << UIndirectList<point>(points, newToOld[newI])
+                    << UIndirectList<point>(points, newToOld[newi])
                     << abort(FatalError);
             }
         }
diff --git a/src/OpenFOAM/containers/CompactLists/CompactListList/CompactListList.H b/src/OpenFOAM/containers/CompactLists/CompactListList/CompactListList.H
index 7935b876a2443bc3fe80937faa096094eda1b3d7..99873e3b805b62fc6c7ceeb49ca1f97fd8080b01 100644
--- a/src/OpenFOAM/containers/CompactLists/CompactListList/CompactListList.H
+++ b/src/OpenFOAM/containers/CompactLists/CompactListList/CompactListList.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2019-2023 OpenCFD Ltd.
+    Copyright (C) 2019-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -63,6 +63,11 @@ template<class T> class CompactListList;
 template<class T> Istream& operator>>(Istream&, CompactListList<T>&);
 template<class T> Ostream& operator<<(Ostream&, const CompactListList<T>&);
 
+// Common list types
+
+//! A CompactListList of labels
+typedef CompactListList<label> labelCompactListList;
+
 
 /*---------------------------------------------------------------------------*\
                        Class CompactListList Declaration
@@ -422,17 +427,17 @@ public:
 
     // Row-based access
 
+        //- Return const access to sub-list (no subscript checking)
+        inline const SubList<T> localList(const label i) const;
+
         //- Return non-const access to sub-list (no subscript checking)
-        inline UList<T> localList(const label i);
+        inline SubList<T> localList(const label i);
 
         //- Return const access to sub-list (no subscript checking)
-        inline const UList<T> localList(const label i) const;
-
-        //- Return row as UList - same as localList method
-        inline UList<T> operator[](const label i);
+        inline const SubList<T> operator[](const label i) const;
 
-        //- Return row as const UList - same as localList method
-        inline const UList<T> operator[](const label i) const;
+        //- Return non-const access to sub-list (no subscript checking)
+        inline SubList<T> operator[](const label i);
 
 
     // Element access
diff --git a/src/OpenFOAM/containers/CompactLists/CompactListList/CompactListListI.H b/src/OpenFOAM/containers/CompactLists/CompactListList/CompactListListI.H
index e5c76d8c855da1e80d8b93d8b1b5752eb3cdcced..41c0ed19e976d718fe9451439ee11ae95181d437 100644
--- a/src/OpenFOAM/containers/CompactLists/CompactListList/CompactListListI.H
+++ b/src/OpenFOAM/containers/CompactLists/CompactListList/CompactListListI.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2019-2023 OpenCFD Ltd.
+    Copyright (C) 2019-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -81,7 +81,6 @@ inline Foam::CompactListList<T>::CompactListList
 {}
 
 
-
 template<class T>
 inline Foam::CompactListList<T>::CompactListList
 (
@@ -259,16 +258,16 @@ inline Foam::label Foam::CompactListList<T>::localSize(const label i) const
 
 
 template<class T>
-inline Foam::UList<T>
-Foam::CompactListList<T>::localList(const label i)
+inline const Foam::SubList<T>
+Foam::CompactListList<T>::localList(const label i) const
 {
     return SubList<T>(values_, (offsets_[i+1] - offsets_[i]), offsets_[i]);
 }
 
 
 template<class T>
-inline const Foam::UList<T>
-Foam::CompactListList<T>::localList(const label i) const
+inline Foam::SubList<T>
+Foam::CompactListList<T>::localList(const label i)
 {
     return SubList<T>(values_, (offsets_[i+1] - offsets_[i]), offsets_[i]);
 }
@@ -476,17 +475,19 @@ inline void Foam::CompactListList<T>::operator=(const Foam::zero)
 
 
 template<class T>
-inline Foam::UList<T>
-Foam::CompactListList<T>::operator[](const label i)
+inline const Foam::SubList<T>
+Foam::CompactListList<T>::operator[](const label i) const
 {
+    // return SubList<T>(values_, (offsets_[i+1] - offsets_[i]), offsets_[i]);
     return this->localList(i);
 }
 
 
 template<class T>
-inline const Foam::UList<T>
-Foam::CompactListList<T>::operator[](const label i) const
+inline Foam::SubList<T>
+Foam::CompactListList<T>::operator[](const label i)
 {
+    // return SubList<T>(values_, (offsets_[i+1] - offsets_[i]), offsets_[i]);
     return this->localList(i);
 }
 
diff --git a/src/OpenFOAM/containers/Lists/ListOps/ListOps.C b/src/OpenFOAM/containers/Lists/ListOps/ListOps.C
index d221f20bb5a89d0fc9e8162270d7ac37e99870a1..172c9e87c542e48ad92a6577e9924e9bb776fe32 100644
--- a/src/OpenFOAM/containers/Lists/ListOps/ListOps.C
+++ b/src/OpenFOAM/containers/Lists/ListOps/ListOps.C
@@ -27,6 +27,7 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "ListOps.H"
+#include "CompactListList.H"
 #include "HashSet.H"
 #include <numeric>
 
@@ -177,6 +178,54 @@ Foam::labelListList Foam::invertOneToMany
 }
 
 
+Foam::CompactListList<Foam::label>
+Foam::invertOneToManyCompact
+(
+    const label len,
+    const labelUList& map
+)
+{
+    labelList sizes(len, Foam::zero{});
+
+    for (const label newIdx : map)
+    {
+        if (newIdx >= 0)
+        {
+            #ifdef FULLDEBUG
+            if (newIdx >= len)
+            {
+                FatalErrorInFunction
+                    << "Inverse location " << newIdx
+                    << " is out of range. List has size " << len
+                    << abort(FatalError);
+            }
+            #endif
+
+            ++sizes[newIdx];
+        }
+    }
+
+    CompactListList<label> inverse(sizes);
+
+    // Reuse sizes as output offset into inverse.values()
+    sizes = labelList::subList(inverse.offsets(), inverse.size());
+    labelList& values = inverse.values();
+
+    label i = 0;
+    for (const label newIdx : map)
+    {
+        if (newIdx >= 0)
+        {
+            values[sizes[newIdx]++] = i;
+        }
+
+        ++i;
+    }
+
+    return inverse;
+}
+
+
 Foam::bitSet Foam::reorder
 (
     const labelUList& oldToNew,
diff --git a/src/OpenFOAM/containers/Lists/ListOps/ListOps.H b/src/OpenFOAM/containers/Lists/ListOps/ListOps.H
index 4b5a1f3adfd24e92a039f70f14f072bf3531c730..3a03da0fb181addba6b45fd47d50fe0448e41628 100644
--- a/src/OpenFOAM/containers/Lists/ListOps/ListOps.H
+++ b/src/OpenFOAM/containers/Lists/ListOps/ListOps.H
@@ -59,6 +59,10 @@ SourceFiles
 namespace Foam
 {
 
+// Forward Declarations
+template<class T> class CompactListList;
+
+
 //- Renumber the values within a list.
 //  Negative input values are left untouched.
 template<class IntListType>
@@ -378,6 +382,13 @@ Map<label> invertToMap(const labelUList& values);
 //- Invert one-to-many map. Unmapped elements will be size 0.
 labelListList invertOneToMany(const label len, const labelUList& map);
 
+//- Invert one-to-many compact map. Unmapped elements will be size 0.
+CompactListList<label> invertOneToManyCompact
+(
+    const label len,
+    const labelUList& map
+);
+
 //- Invert many-to-many.
 //  Input and output types must be inherited from List and also
 //  contain ints/labels. Used, for example, for faces to pointFaces.