#include <bits/stdc++.h>   using namespace std;   template <typename Arg1>   void __f(const char* name, Arg1&& arg1) {     cout << name <<   :   << arg1 <<   n ;   }   template <typename Arg1, typename... Args>   void __f(const char* names, Arg1&& arg1, Args&&... args) {     const char* comma = strchr(names + 1,  , );     cout.write(names, comma - names) <<   :   << arg1 <<   |  ;     __f(comma + 1, args...);   }   const long long int N = 1000005;   struct segmenttree {     vector<long long int> st;     void init(long long int _n) {       st.clear();       st.resize(4 * _n);     }     void build(long long int l, long long int r, long long int node) {       if (l == r) {         return;       }       long long int mid = (l + r) / 2;       build(l, mid, node * 2 + 1);       build(mid + 1, r, node * 2 + 2);       st[node] = max(st[2 * node + 1], st[2 * node + 2]);     }     void update(long long int l, long long int r, long long int indup,                 long long int val, long long int node) {       if (l == r) {         st[node] = val;         return;       } else {         long long int mid = (l + r) / 2;         if (indup >= l && indup <= mid) {           update(l, mid, indup, val, node * 2 + 1);         } else {           update(mid + 1, r, indup, val, node * 2 + 2);         }         st[node] = max(st[2 * node + 1], st[2 * node + 2]);       }     }     long long int query(long long int si, long long int se, long long int l,                         long long int r, long long int node) {       if (se < l || si > r || l > r) {         return INT_MIN;       }       if (si >= l && se <= r) {         return st[node];       }       long long int mid = (si + se) / 2;       long long int q1 = query(si, mid, l, r, node * 2 + 1);       long long int q2 = query(mid + 1, se, l, r, node * 2 + 2);       return max(q1, q2);     }   };   segmenttree tree[N];   long long int sz[N], res[N], mx[N], n, m;   vector<long long int> pos[N];   long long int give(long long int row, long long int pos) {     long long int mn, mx, ret;     if (pos < sz[row]) {       mn = max(0ll, pos - (m - sz[row])), mx = pos;       if ((m - 1) - pos >= sz[row])         ret = 0;       else         ret = INT_MIN;     } else {       pos = sz[row] - (m - pos);       mn = pos, mx = max(sz[row] - 1, pos + (m - sz[row]));       if (pos >= sz[row])         ret = INT_MIN;       else         ret = 0;     }     return max(ret, tree[row].query(0, sz[row] - 1, mn, mx, 0));   }   int32_t main() {     ios_base::sync_with_stdio(false);     cin.tie(NULL);     cout.tie(NULL);     {       long long int i, j, k, ans = 0, cnt = 0, sum = 0;       cin >> n >> m;       for (i = 0; i < n; i++) {         cin >> sz[i];         tree[i].init(sz[i]);         for (j = 0; j < sz[i]; j++) {           long long int x;           cin >> x;           mx[i] = max(mx[i], x);           tree[i].update(0, sz[i] - 1, j, x, 0);         }         for (j = 0; j < sz[i]; j++) pos[j].push_back(i);         for (j = max(sz[i], (m - sz[i])); j < m; j++) pos[j].push_back(i);       }       for (i = 0; i < n; i++) {         ans += mx[i];       }       for (i = 0; i < m; i++) {         res[i] = ans;         for (auto x : pos[i]) {           res[i] -= mx[x];           res[i] += give(x, i);         }       }       for (i = 0; i < m; i++) {         cout << res[i] <<    ;       }     }   }