Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <string>
- #include <vector>
- #include <algorithm>
- #include <cstring>
- #include <cassert>
- #include <iostream>
- using namespace std;
- vector<string> v;
- int memo[30][100000], prizes[30], l;
- vector<int> ans;
- void endgame(int mask) {
- for(int i = 0; i < l; i++)
- if((mask & (1<<i)) == 0)
- ans.push_back(i+1);
- }
- int doit(int size, int first, int last, int mask, bool track) {
- int& ret = memo[size][first];
- if(!track) {
- if(ret != -1) return ret;
- ret = 0x3f3f3f3f;
- }
- int lo, hi;
- if(((1<<(v[first][size]-1)) & mask) == 0) {
- int mask2 = mask | (1<<(v[first][size]-1));
- lo = first; hi = last+1;
- while(lo < hi) {
- int mid = (lo + hi)/2;
- if(v[mid].size() == size+1 && v[mid][size] == v[first][size])
- lo = mid+1;
- else
- hi = mid;
- }
- int prize = (lo-first) * prizes[size];
- int first2 = lo;
- if(first2 <= last && v[first2][size] == v[first][size]) {
- // Skipped over 0 -> v[first2][size+1]-1. Any holes?
- int msk = ((1<<(v[first2][size+1]-1))-1) & ~mask2;
- if(msk) {
- if(track && ret == prize) {
- ans.push_back(v[first][size]);
- int lst = __builtin_ffs(msk)-1;
- ans.push_back(lst+1);
- endgame(mask2 | (1<<lst));
- return ret;
- }
- ret = min(ret, prize);
- }
- // Nope, no holes, adjust last correctly
- lo = first2, hi = last;
- while(lo < hi) {
- int mid = (lo+hi+1)/2;
- if(v[mid][size] != v[first][size])
- hi = mid-1;
- else
- lo = mid;
- }
- if(track && prize + doit(size+1, first2, lo, mask2, false) == ret) {
- ans.push_back(v[first][size]);
- doit(size+1, first2, lo, mask2, true);
- return ret;
- }
- ret = min(ret, prize + doit(size+1, first2, lo, mask2, false));
- } else {
- if(track && prize == ret) {
- ans.push_back(v[first][size]);
- endgame(mask2);
- return ret;
- }
- ret = min(ret, prize);
- }
- }
- lo = first; hi = last;
- if(v[first][size] != v[last][size]) {
- while(lo < hi) {
- int mid = (lo+hi)/2;
- if(v[mid][size] > v[first][size])
- hi = mid;
- else
- lo = mid+1;
- }
- // Skipped over v[first][size]+1 -> v[lo][size]-1, check for holes
- int msk = ((1<<(v[lo][size]-1))-1) &
- (~((1<<v[first][size])-1)) & ~mask;
- if(msk) {
- if(track) {
- int lst = __builtin_ffs(msk)-1;
- ans.push_back(lst+1);
- endgame(mask | (1<<lst));
- return 0;
- }
- return ret = 0;
- }
- if(track && doit(size, lo, last, mask, false) == ret) {
- doit(size, lo, last, mask, true);
- return ret;
- }
- ret = min(ret, doit(size, lo, last, mask, false));
- } else {
- // Skipped over v[last][size]+1 -> l-1. Holes?
- int msk = ((1<<l)-1) & (~((1<<v[last][size])-1)) & ~mask;
- if(msk) {
- if(track) {
- int lst = __builtin_ffs(msk)-1;
- ans.push_back(lst+1);
- endgame(mask | (1<<lst));
- return 0;
- }
- return ret = 0;
- }
- }
- return ret;
- }
- int main() {
- int t;
- scanf("%d", &t);
- for(int i = 0; i < t; i++) {
- v.clear();
- int n;
- scanf("%d %d", &l, &n);
- for(int j = 0; j < l; j++)
- scanf("%d", &prizes[j]);
- for(int j = 0; j < n; j++) {
- int sz;
- scanf("%d", &sz);
- string s(sz, (char)1);
- int tmp;
- for(int k = 0; k < sz; k++) {
- scanf("%d", &tmp);
- s[k] = tmp;
- }
- v.push_back(s);
- }
- sort(v.begin(), v.end());
- memset(memo, -1, sizeof memo);
- doit(0, 0, v.size() - 1, 0, false);
- ans.clear();
- doit(0, 0, v.size() - 1, 0, true);
- int cst = 0;
- for(int i = 0; i < n; i++) {
- bool ok = true;
- for(int j = 0; j < v[i].size(); j++)
- if(v[i][j] != ans[j])
- ok = false;
- if(ok) cst += prizes[v[i].size()-1];
- }
- assert(doit(0, 0, v.size() - 1, 0, false) == cst);
- printf("%d", ans[0]);
- for(int i = 1; i < l; i++)
- printf(" %d", ans[i]);
- printf("\n");
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement