#include #define ll long long #define ull unsigned long long using namespace std; const int MAXN = 1e4 + 5; const int MAXM = 5e3 + 5; const int LIM = 2000000; int N, M, P[MAXN], sol[MAXM], temp[MAXM], S[MAXN]; pair LR[MAXN]; ll SCORE, TSCORE, TEMPSCORE; vector V[MAXM]; clock_t start, finish; int limit = 4.8 * CLOCKS_PER_SEC; int sz; mt19937_64 rng; char BUF[LIM], *p; inline int Read() { char c; while ((c = *p++) < '0'); int x = c - '0'; while ((c = *p++) >= '0') x *= 10, x += c - '0'; return x; } void ADD(int idx, int s, int v, ull *A) { int i = (idx >> 6); ull j = idx & 63; A[s * sz + i] ^= (1ULL << j); return; } int FINDL(int s, ull *A) { ull i = 0; while(!A[s * sz + i]) i++; return (i << 6ULL) + __builtin_ffsll(A[s * sz + i]) - 1; } int FINDR(int s, ull *A) { ull i = sz - 1; while(!A[s * sz + i]) i--; return (i << 6ULL) + 64 - __builtin_clzll(A[s * sz + i]) - 1; } ll FIRST(ull *A) { TSCORE = 0; for(int i = 1; i <= N; i++) LR[i].first = FINDL(i, A), LR[i].second = FINDR(i, A); for(int i = 1; i <= N; i++) TSCORE += P[i] * (LR[i].second - LR[i].first + 1LL); return TSCORE; } bool EVALUATE(int idx1, int idx2, ull *A) { int pos1 = temp[idx1]; int pos2 = temp[idx2]; TSCORE = TEMPSCORE; for(int x : V[pos1]) { TSCORE -= P[x] * (LR[x].second - LR[x].first + 1LL); ADD(idx1, x, -1, A); ADD(idx2, x, 1, A); } for(int x : V[pos2]) { TSCORE -= P[x] * (LR[x].second - LR[x].first + 1LL); ADD(idx2, x, -1, A); ADD(idx1, x, 1, A); } for(int x : V[pos1]) { LR[x].first = FINDL(x, A); LR[x].second = FINDR(x, A); } for(int x : V[pos2]) { LR[x].first = FINDL(x, A); LR[x].second = FINDR(x, A); } for(int x : V[pos1]) TSCORE += P[x] * (LR[x].second - LR[x].first + 1LL); for(int x : V[pos2]) TSCORE += P[x] * (LR[x].second - LR[x].first + 1LL); if(TSCORE < TEMPSCORE) return true; else { for(int x : V[pos1]) { ADD(idx1, x, 1, A); ADD(idx2, x, -1, A); LR[x].first = FINDL(x, A); LR[x].second = FINDR(x, A); } for(int x : V[pos2]) { ADD(idx2, x, 1, A); ADD(idx1, x, -1, A); LR[x].first = FINDL(x, A); LR[x].second = FINDR(x, A); } return false; } } void SOLVE() { SCORE = 1e18; start = clock(); rng.seed(1); for(int i = 1; i <= M; i++) sol[i] = i; for(int i = 1; i <= M; i++) temp[i] = i; sz = (M >> 6) + 1; ull A[(N + 5) * sz]; memset(A, 0, sizeof(A)); for(int i = 1; i <= M; i++) for(int x : V[i]) ADD(i, x, 1, A); ll first = TEMPSCORE = FIRST(A); int cnt = 0; int iter = 0; int M2 = M * M; if(M < 1000) { while(clock() - start <= limit) { iter++; if((cnt << 1) >= M2) { cnt = 0; if(TEMPSCORE < SCORE) swap(sol, temp), SCORE = TEMPSCORE; for(int i = 1; i <= M; i++) temp[i] = i; if(N * sz < 1000000) for(int i = 0; i <= N * sz; i++) A[i] = 0; else __builtin_memset(A, 0, sizeof(A)); for(int i = 1; i <= M; i++) for(int x : V[i]) ADD(i, x, 1, A); for(int i = 1; i <= N; i++) LR[i].first = FINDL(i, A), LR[i].second = FINDR(i, A); TEMPSCORE = first; } int idx1 = rand() % M + 1; int idx2 = rand() % M + 1; if(idx1 == idx2) continue; if(EVALUATE(idx1, idx2, A)) { cnt = 0; TEMPSCORE = TSCORE; swap(temp[idx1], temp[idx2]); } cnt++; } } else { while(clock() - start <= limit) { iter++; int idx1 = rand() % M + 1; int idx2 = rand() % M + 1; if(idx1 == idx2) continue; if(EVALUATE(idx1, idx2, A)) { cnt = 0; TEMPSCORE = TSCORE; swap(temp[idx1], temp[idx2]); } cnt++; } } if(TEMPSCORE < SCORE) swap(sol, temp), SCORE = TEMPSCORE; cout << "ITERATIONS " << iter << "\n"; return; } void INPUT() { freopen("star.in", "r", stdin); fread(BUF, 1, LIM, stdin); p = BUF; N = Read(); M = Read(); for(int i = 1; i <= N; i++) P[i] = Read(); for(int i = 1; i <= M; i++) { int vs = Read(); for(int j = 1; j <= vs; j++) { int x = Read(); V[i].push_back(x); S[x]++; } } return; } void OUTPUT() { cout << "FINAL SCORE = " << SCORE << "\n"; freopen("star.out", "w", stdout); for(int i = 1; i <= M; i++) cout << sol[i] << " "; cout << "\n"; } int main() { INPUT(); SOLVE(); OUTPUT(); return 0; }