vl ntt_rev(vl& a) { vl res = ntt(a); ll in = inv(a.size()); F0R(i,sz(res)) res[i] = res[i]*in % mod; reverse(res.begin() + 1, res.end()); return res; }
int lis(const vl& in, vi& liss, vi& parents) { // position j gives index of the last element in "best" // known lis of length j (where best means ends in // smallest element) vi length_idx(in.size() + 1, -1); // position i gives the immediate predecessor of element i // in best known lis parents.resize(in.size(), -1); // gives the length of the best known lis ending in pos i liss.resize(in.size(), -1); // best known length int L = 0; for(int i = 0; i < in.size(); ++i) { // binary search for largest pos j <= L s.t. // in[length_idx[j]] < in[i] // i.e. the lis we can append in[i] onto int low = 1, high = L; while(low <= high) { int mid = ceil((low+high)/2); if(in[length_idx[mid]] < in[i]) low = mid+1; else high = mid-1; } // low is length of lis ending in in[i] parents[i] = length_idx[low-1]; length_idx[low] = i; liss[i] = low; // update best known length L = max(L, low); } return L; }
void unionEquals(vl & G, DisjointSet &ds, CmpByMask cmp) { for (uint i = 0; i < G.size() - 1; ++i) { /* if previous less than next */ if (cmp(G[i], G[i + 1])) { continue; } /* two adjacent nodes are equal */ /* check if they belong to different component and union them */ /* BUG: keep index in G */ if (ds.findSet(i) != ds.findSet(i + 1)) { ds.unionNodes(i, i + 1); } } }