public static int GetGameLifeSpan(List <Rectangle> rectangles)
        {
            var sets  = UnionFind.CreateSubsets(n);
            var minXY = new int[n];
            var maxX  = new int[n];
            var maxY  = new int[n];

            for (int i = 0; i < n; i++)
            {
                var rec = rectangles[i];
                minXY[i] = rec.x1 + rec.y1;
                maxX[i]  = rec.x2;
                maxY[i]  = rec.y2;

                for (int j = 0; j < i; j++)
                {
                    var recp = rectangles[j];

                    if (!(rec.x2 + 1 < recp.x1 || rec.y2 + 1 < recp.y1 || rec.x1 - 1 > recp.x2 || rec.y1 - 1 > recp.y2) &&
                        !(rec.x2 + 1 == recp.x1 && rec.y2 + 1 == recp.y1) &&
                        !(recp.x2 + 1 == rec.x1 && recp.y2 + 1 == rec.y1))
                    {
                        int ii = UnionFind.Find(sets, i);
                        int jj = UnionFind.Find(sets, j);
                        UnionFind.Union(sets, ii, jj);

                        int k = UnionFind.Find(sets, ii);

                        minXY[k] = Math.Min(Math.Min(minXY[k], minXY[ii]), minXY[jj]);
                        maxX[k]  = Math.Max(Math.Max(maxX[k], maxX[ii]), maxX[jj]);
                        maxY[k]  = Math.Max(Math.Max(maxY[k], maxY[ii]), maxY[jj]);
                    }
                }
            }

            int lifes = 0;

            for (int i = 0; i < n; i++)
            {
                int parent = UnionFind.Find(sets, i);

                lifes = Math.Max(lifes, maxX[parent] + maxY[parent] - minXY[parent] + 1);
            }

            return(lifes);
        }