Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Discrete log
- int solve (int a, int b, int m) {
- int n = (int) sqrt (m + .0) + 1;
- int an = 1;
- for (int i=0; i<n; ++i)
- an = (an * a) % m;
- map<int,int> vals;
- for (int i=1, cur=an; i<=n; ++i) {
- if (!vals.count(cur))
- vals[cur] = i;
- cur = (cur * an) % m;
- }
- for (int i=0, cur=b; i<=n; ++i) {
- if (vals.count(cur)) {
- int ans = vals[cur] * n - i;
- if (ans < m)
- return ans;
- }
- cur = (cur * a) % m;
- }
- return -1;
- }
- /*
- Пусть дан граф G с n вершинами. Построим соответствующий ему двудольный граф H стандартным образом, т.е.: в каждой доле графа H будет по n вершин, обозначим их через a_i и b_i соответственно. Тогда для каждого ребра (i, j) исходного графа G проведём соответствующее ребро (a_i, b_j).
- */
- /*
- Формула Кэли
- s1 * s2 ... * sk * n ^ (k - 2)
- */
- template<class T> struct MinDeque {
- int lo = 0, hi = -1;
- deque<pair<T,int>> d;
- int size() { return hi-lo+1; }
- void push(T x) { // add to back
- while (sz(d) && d.back().f >= x) d.pop_back();
- d.pb({x,++hi});
- }
- void pop() { // delete from front
- assert(size());
- if (d.front().s == lo++) d.pop_front();
- }
- T mn() { return size() ? d.front().f : MOD; }
- // change MOD based on T
- };
- template<int SZ> struct Wavelet {
- vi nexl[SZ], nexr[SZ];
- void build(vi a, int ind = 1, int L = 0, int R = SZ-1) {
- if (L == R) return;
- nexl[ind] = nexr[ind] = {0};
- vi A[2]; int M = (L+R)/2;
- trav(t,a) {
- A[t>M].pb(t);
- nexl[ind].pb(sz(A[0])), nexr[ind].pb(sz(A[1]));
- }
- build(A[0],2*ind,L,M), build(A[1],2*ind+1,M+1,R);
- }
- int query(int lo,int hi,int k,int ind=1,int L=0,int R=SZ-1) {
- if (L == R) return L;
- int M = (L+R)/2, t = nexl[ind][hi]-nexl[ind][lo];
- if (t >= k) return query(nexl[ind][lo],
- nexl[ind][hi],k,2*ind,L,M);
- return query(nexr[ind][lo],
- nexr[ind][hi],k-t,2*ind+1,M+1,R);
- }
- };
- template<class T, int SZ> struct BITrange {
- BIT<T,SZ> bit[2]; // piecewise linear functions
- // let cum[x] = sum_{i=1}^{x}a[i]
- void upd(int hi, T val) { // add val to a[1..hi]
- // if x <= hi, cum[x] += val*x
- bit[1].upd(1,val), bit[1].upd(hi+1,-val);
- // if x > hi, cum[x] += val*hi
- bit[0].upd(hi+1,hi*val);
- }
- void upd(int lo, int hi, T val) {
- upd(lo-1,-val), upd(hi,val); }
- T sum(int x) { return bit[1].sum(x)*x+bit[0].sum(x); }
- T query(int x, int y) { return sum(y)-sum(x-1); }
- };
- /**
- * Description: Supports modifications in the form \texttt{ckmin(a\_i,t)}
- * for all $l\le i\le r$, range max and sum queries. SZ should be a power of 2.
- * Time: O(\log N)
- * Source: http://codeforces.com/blog/entry/57319
- * Verification: http://acm.hdu.edu.cn/showproblem.php?pid=5306
- */
- template<int SZ> struct SegTreeBeats {
- int N, mx[2*SZ][2], maxCnt[2*SZ];
- ll sum[2*SZ];
- void pull(int ind) {
- F0R(i,2) mx[ind][i] = max(mx[2*ind][i],mx[2*ind+1][i]);
- maxCnt[ind] = 0;
- F0R(i,2) {
- if (mx[2*ind+i][0] == mx[ind][0])
- maxCnt[ind] += maxCnt[2*ind+i];
- else ckmax(mx[ind][1],mx[2*ind+i][0]);
- }
- sum[ind] = sum[2*ind]+sum[2*ind+1];
- }
- void build(vi& a, int ind = 1, int L = 0, int R = -1) {
- if (R == -1) { R = (N = sz(a))-1; }
- if (L == R) {
- mx[ind][0] = sum[ind] = a[L];
- maxCnt[ind] = 1; mx[ind][1] = -1;
- return;
- }
- int M = (L+R)/2;
- build(a,2*ind,L,M); build(a,2*ind+1,M+1,R); pull(ind);
- }
- void push(int ind, int L, int R) {
- if (L == R) return;
- F0R(i,2) if (mx[2*ind^i][0] > mx[ind][0]) {
- sum[2*ind^i] -= (ll)maxCnt[2*ind^i]*
- (mx[2*ind^i][0]-mx[ind][0]);
- mx[2*ind^i][0] = mx[ind][0];
- }
- }
- void upd(int x, int y, int t, int ind=1, int L=0, int R=-1) {
- if (R == -1) R += N;
- if (R < x || y < L || mx[ind][0] <= t) return;
- push(ind,L,R);
- if (x <= L && R <= y && mx[ind][1] < t) {
- sum[ind] -= (ll)maxCnt[ind]*(mx[ind][0]-t);
- mx[ind][0] = t;
- return;
- }
- if (L == R) return;
- int M = (L+R)/2;
- upd(x,y,t,2*ind,L,M); upd(x,y,t,2*ind+1,M+1,R); pull(ind);
- }
- ll qsum(int x, int y, int ind = 1, int L = 0, int R = -1) {
- if (R == -1) R += N;
- if (R < x || y < L) return 0;
- push(ind,L,R);
- if (x <= L && R <= y) return sum[ind];
- int M = (L+R)/2;
- return qsum(x,y,2*ind,L,M)+qsum(x,y,2*ind+1,M+1,R);
- }
- int qmax(int x, int y, int ind = 1, int L = 0, int R = -1) {
- if (R == -1) R += N;
- if (R < x || y < L) return -1;
- push(ind,L,R);
- if (x <= L && R <= y) return mx[ind][0];
- int M = (L+R)/2;
- return max(qmax(x,y,2*ind,L,M),qmax(x,y,2*ind+1,M+1,R));
- }
- };
- // Directed MST
- struct Edge { int a, b; ll w; };
- struct Node { // lazy skew heap node
- Edge key;
- Node *l, *r;
- ll delta;
- void prop() {
- key.w += delta;
- if (l) l->delta += delta;
- if (r) r->delta += delta;
- delta = 0;
- }
- Edge top() { prop(); return key; }
- };
- Node *merge(Node *a, Node *b) {
- if (!a || !b) return a ?: b;
- a->prop(), b->prop();
- if (a->key.w > b->key.w) swap(a, b);
- swap(a->l, a->r = merge(b, a->r));
- return a;
- }
- void pop(Node*& a) { a->prop(); a = merge(a->l, a->r); }
- pair<ll,vi> dmst(int n, int r, const vector<Edge>& g) {
- DSUrb dsu; dsu.init(n);
- vector<Node*> heap(n); // store edges entering each vertex
- // in increasing order of weight
- trav(e,g) heap[e.b] = merge(heap[e.b], new Node{e});
- ll res = 0; vi seen(n,-1); seen[r] = r;
- vpi in(n,{-1,-1}); // edge entering each vertex in MST
- vector<pair<int,vector<Edge>>> cycs;
- F0R(s,n) {
- int u = s, w;
- vector<pair<int,Edge>> path;
- while (seen[u] < 0) {
- if (!heap[u]) return {-1,{}};
- seen[u] = s;
- Edge e = heap[u]->top(); path.pb({u,e});
- heap[u]->delta -= e.w, pop(heap[u]);
- res += e.w, u = dsu.get(e.a);
- if (seen[u] == s) { // found cycle, contract
- Node* cyc = 0; cycs.eb();
- do {
- cyc = merge(cyc, heap[w = path.bk.f]);
- cycs.bk.s.pb(path.bk.s);
- path.pop_back();
- } while (dsu.unite(u,w));
- u = dsu.get(u); heap[u] = cyc, seen[u] = -1;
- cycs.bk.f = u;
- }
- }
- trav(t,path) in[dsu.get(t.s.b)] = {t.s.a,t.s.b};
- // found path from root to s, done
- }
- while (sz(cycs)) { // expand cycs to restore sol
- auto c = cycs.bk; cycs.pop_back();
- pi inEdge = in[c.f];
- trav(t,c.s) dsu.rol.bk;
- trav(t,c.s) in[dsu.get(t.b)] = {t.a,t.b};
- in[dsu.get(inEdge.s)] = inEdge;
- }
- vi par(n); F0R(i,n) par[i] = in[i].f;
- // i == r ? in[i].s == -1 : in[i].s == i
- return {res,par};
- }
- template<int SZ> struct EdgeColor {
- int N = 0, maxDeg = 0, adj[SZ][SZ], deg[SZ];
- EdgeColor() {
- memset(adj,0,sizeof adj);
- memset(deg,0,sizeof deg);
- }
- void ae(int a, int b, int c) {
- adj[a][b] = adj[b][a] = c; }
- int delEdge(int a, int b) {
- int c = adj[a][b]; adj[a][b] = adj[b][a] = 0;
- return c;
- }
- vector<bool> genCol(int x) {
- vector<bool> col(N+1); F0R(i,N) col[adj[x][i]] = 1;
- return col;
- }
- int freeCol(int u) {
- auto col = genCol(u);
- int x = 1; while (col[x]) x ++; return x;
- }
- void invert(int x, int d, int c) {
- F0R(i,N) if (adj[x][i] == d)
- delEdge(x,i), invert(i,c,d), ae(x,i,c);
- }
- void ae(int u, int v) { // follows wikipedia steps
- // check if you can add edge w/o doing any work
- assert(N); ckmax(maxDeg,max(++deg[u],++deg[v]));
- auto a = genCol(u), b = genCol(v);
- FOR(i,1,maxDeg+2) if (!a[i] && !b[i])
- return ae(u,v,i);
- // 2. find maximal fan of u starting at v
- vector<bool> use(N); vi fan = {v}; use[v] = 1;
- while (1) {
- auto col = genCol(fan.bk);
- if (sz(fan) > 1) col[adj[fan.bk][u]] = 0;
- int i = 0; while (i < N && (use[i] || col[adj[u][i]])) i ++;
- if (i < N) fan.pb(i), use[i] = 1;
- else break;
- }
- // 3/4. choose free cols for endpoints of fan, invert cd_u path
- int c = freeCol(u), d = freeCol(fan.bk); invert(u,d,c);
- // 5. find i such that d is free on fan[i]
- int i = 0; while (i < sz(fan) && genCol(fan[i])[d]
- && adj[u][fan[i]] != d) i ++;
- assert (i != sz(fan));
- // 6. rotate fan from 0 to i
- F0R(j,i) ae(u,fan[j],delEdge(u,fan[j+1]));
- // 7. add new edge
- ae(u,fan[i],d);
- }
- };
- /**
- * Description: Used only once. Finds all maximal cliques.
- * Time: O(3^{N/3})
- * Source: KACTL
- * Verification: BOSPRE 2016 gaudy
- */
- typedef bitset<128> B;
- int N;
- B adj[128];
- // possibly in clique, not in clique, in clique
- void cliques(B P = ~B(), B X={}, B R={}) {
- if (!P.any()) {
- if (!X.any()) {
- // do smth with R
- }
- return;
- }
- int q = (P|X)._Find_first();
- // clique must contain q or non-neighbor of q
- B cands = P&~adj[q];
- F0R(i,N) if (cands[i]) {
- R[i] = 1;
- cliques(P&adj[i],X&adj[i],R);
- R[i] = P[i] = 0; X[i] = 1;
- }
- }
- // Linear Recurence
- vector<int> berlekamp(vector<int> s) {
- int l = 0;
- vector<int> la(1, 1);
- vector<int> b(1, 1);
- for (int r = 1; r <= (int)s.size(); r++) {
- int delta = 0;
- for (int j = 0; j <= l; j++) {
- delta = (delta + 1LL * s[r - 1 - j] * la[j]) % MOD;
- }
- b.insert(b.begin(), 0);
- if (delta != 0) {
- vector<int> t(max(la.size(), b.size()));
- for (int i = 0; i < (int)t.size(); i++) {
- if (i < (int)la.size()) t[i] = (t[i] + la[i]) % MOD;
- if (i < (int)b.size()) t[i] = (t[i] - 1LL * delta * b[i] % MOD + MOD) % MOD;
- }
- if (2 * l <= r - 1) {
- b = la;
- int od = inv(delta);
- for (int &x : b) x = 1LL * x * od % MOD;
- l = r - l;
- }
- la = t;
- }
- }
- assert((int)la.size() == l + 1);
- assert(l * 2 + 30 < (int)s.size());
- reverse(la.begin(), la.end());
- return la;
- }
- vector<int> mul(vector<int> a, vector<int> b) {
- vector<int> c(a.size() + b.size() - 1);
- for (int i = 0; i < (int)a.size(); i++) {
- for (int j = 0; j < (int)b.size(); j++) {
- c[i + j] = (c[i + j] + 1LL * a[i] * b[j]) % MOD;
- }
- }
- vector<int> res(c.size());
- for (int i = 0; i < (int)res.size(); i++) res[i] = c[i] % MOD;
- return res;
- }
- vector<int> mod(vector<int> a, vector<int> b) {
- if (a.size() < b.size()) a.resize(b.size() - 1);
- int o = inv(b.back());
- for (int i = (int)a.size() - 1; i >= (int)b.size() - 1; i--) {
- if (a[i] == 0) continue;
- int coef = 1LL * o * (MOD - a[i]) % MOD;
- for (int j = 0; j < (int)b.size(); j++) {
- a[i - (int)b.size() + 1 + j] = (a[i - (int)b.size() + 1 + j] + 1LL * coef * b[j]) % MOD;
- }
- }
- while (a.size() >= b.size()) {
- assert(a.back() == 0);
- a.pop_back();
- }
- return a;
- }
- vector<int> bin(int n, vector<int> p) {
- vector<int> res(1, 1);
- vector<int> a(2); a[1] = 1;
- while (n) {
- if (n & 1) res = mod(mul(res, a), p);
- a = mod(mul(a, a), p);
- n >>= 1;
- }
- return res;
- }
- int f(vector<int> t, int m) {
- vector<int> v = berlekamp(t);
- vector<int> o = bin(m - 1, v);
- int res = 0;
- for (int i = 0; i < (int)o.size(); i++) res = (res + 1LL * o[i] * t[i]) % MOD;
- return res;
- }
- // Split-merge sqrt
- const int pivo = 3e5 + 555, magic = 700;
- int ex[pivo];
- vector<int> s[magic];
- int mn[pivo], mx[pivo], psz[pivo];
- int n, q;
- void rebuild() {
- vector<int> order;
- for (int i = 0; i < magic; i++) {
- for (auto j : s[i]) order.push_back(j);
- s[i].clear();
- }
- for (int i = 0; i < n; i++) {
- s[i / magic].push_back(order[i]);
- ex[order[i]] = i / magic;
- }
- }
- signed main() {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cin >> n >> q;
- for (int i = 1; i <= n; i++) {
- mx[i] = mn[i] = i;
- s[i / magic].push_back(i);
- ex[i] = i / magic;
- }
- while(q--) {
- int x;
- cin >> x;
- int sz = 0;
- for (int i = 0; i < magic; i++) {
- if (ex[x] == i) {
- ex[x] = 0;
- auto it = find(s[i].begin(), s[i].end(), x);
- mx[x] = max(mx[x], sz + 1 + (it - s[i].begin()));
- mn[x] = 1;
- s[i].erase(it);
- s[0].insert(s[0].begin(), x);
- break;
- }
- sz += s[i].size();
- }
- if (s[0].size() > 4 * magic) rebuild();
- }
- vector<int> order;
- for (int i = 0; i < magic; i++) {
- for (auto j : s[i]) order.push_back(j);
- }
- for (int i = 0; i < n; i++) mn[order[i]] = min(mn[order[i]], i + 1), mx[order[i]] = max(mx[order[i]], i + 1);
- for (int i = 1; i <= n; i++) cout << mn[i] << " " << mx[i] << endl;
- }
- template<int SZ> struct EdgeColor {
- int N = 0, maxDeg = 0, adj[SZ][SZ], deg[SZ];
- EdgeColor() {
- memset(adj,0,sizeof adj);
- memset(deg,0,sizeof deg);
- }
- void ae(int a, int b, int c) {
- adj[a][b] = adj[b][a] = c; }
- int delEdge(int a, int b) {
- int c = adj[a][b]; adj[a][b] = adj[b][a] = 0;
- return c;
- }
- vector<bool> genCol(int x) {
- vector<bool> col(N+1); F0R(i,N) col[adj[x][i]] = 1;
- return col;
- }
- int freeCol(int u) {
- auto col = genCol(u);
- int x = 1; while (col[x]) x ++; return x;
- }
- void invert(int x, int d, int c) {
- F0R(i,N) if (adj[x][i] == d)
- delEdge(x,i), invert(i,c,d), ae(x,i,c);
- }
- void ae(int u, int v) { // follows wikipedia steps
- // check if you can add edge w/o doing any work
- assert(N); ckmax(maxDeg,max(++deg[u],++deg[v]));
- auto a = genCol(u), b = genCol(v);
- FOR(i,1,maxDeg+2) if (!a[i] && !b[i])
- return ae(u,v,i);
- // 2. find maximal fan of u starting at v
- vector<bool> use(N); vi fan = {v}; use[v] = 1;
- while (1) {
- auto col = genCol(fan.bk);
- if (sz(fan) > 1) col[adj[fan.bk][u]] = 0;
- int i = 0; while (i < N && (use[i] || col[adj[u][i]])) i ++;
- if (i < N) fan.pb(i), use[i] = 1;
- else break;
- }
- // 3/4. choose free cols for endpoints of fan, invert cd_u path
- int c = freeCol(u), d = freeCol(fan.bk); invert(u,d,c);
- // 5. find i such that d is free on fan[i]
- int i = 0; while (i < sz(fan) && genCol(fan[i])[d]
- && adj[u][fan[i]] != d) i ++;
- assert (i != sz(fan));
- // 6. rotate fan from 0 to i
- F0R(j,i) ae(u,fan[j],delEdge(u,fan[j+1]));
- // 7. add new edge
- ae(u,fan[i],d);
- }
- };
- vector<pair<int,pi>> manhattanMst(vpi v) {
- vi id(sz(v)); iota(all(id),0);
- vector<pair<int,pi>> ed;
- F0R(k,4) {
- sort(all(id),[&](int i, int j) {
- return v[i].f+v[i].s < v[j].f+v[j].s; });
- map<int,int> sweep;
- trav(i,id) { // find neighbors for first octant
- for (auto it = sweep.lb(-v[i].s);
- it != end(sweep); sweep.erase(it++)) {
- int j = it->s;
- pi d = {v[i].f-v[j].f,v[i].s-v[j].s};
- if (d.s > d.f) break;
- ed.pb({d.f+d.s,{i,j}});
- }
- sweep[-v[i].s] = i;
- }
- trav(p,v) {
- if (k&1) p.f *= -1;
- else swap(p.f,p.s);
- }
- }
- return ed;
- }
- // Perm
- vi decode(int n, int a) {
- vi el(n), b; iota(all(el),0);
- F0R(i,n) {
- int z = a%sz(el);
- b.pb(el[z]); a /= sz(el);
- swap(el[z],el.bk); el.pop_back();
- }
- return b;
- }
- int encode(vi b) {
- int n = sz(b), a = 0, mul = 1;
- vi pos(n); iota(all(pos),0); vi el = pos;
- F0R(i,n) {
- int z = pos[b[i]]; a += mul*z; mul *= sz(el);
- swap(pos[el[z]],pos[el.bk]);
- swap(el[z],el.bk); el.pop_back();
- }
- return a;
- }
- // PermGroup
- int n;
- vi inv(vi v) { vi V(sz(v)); F0R(i,sz(v)) V[v[i]]=i; return V; }
- vi id() { vi v(n); iota(all(v),0); return v; }
- vi operator*(const vi& a, const vi& b) {
- vi c(sz(a)); F0R(i,sz(a)) c[i] = a[b[i]];
- return c;
- }
- const int N = 15;
- struct Group {
- bool flag[N];
- vi sigma[N]; // sigma[t][k] = t, sigma[t][x] = x if x > k
- vector<vi> gen;
- void clear(int p) {
- memset(flag,0, sizeof flag);
- flag[p] = 1; sigma[p] = id();
- gen.clear();
- }
- } g[N];
- bool check(const vi& cur, int k) {
- if (!k) return 1;
- int t = cur[k];
- return g[k].flag[t] ? check(inv(g[k].sigma[t])*cur,k-1) : 0;
- }
- void updateX(const vi& cur, int k);
- void ins(const vi& cur, int k) {
- if (check(cur,k)) return;
- g[k].gen.pb(cur);
- F0R(i,n) if (g[k].flag[i]) updateX(cur*g[k].sigma[i],k);
- }
- void updateX(const vi& cur, int k) {
- int t = cur[k]; // if flag, fixes k -> k
- if (g[k].flag[t]) ins(inv(g[k].sigma[t])*cur,k-1);
- else {
- g[k].flag[t] = 1, g[k].sigma[t] = cur;
- trav(x,g[k].gen) updateX(x*cur,k);
- }
- }
- ll order(vector<vi> gen) {
- assert(sz(gen)); n = sz(gen[0]); F0R(i,n) g[i].clear(i);
- trav(a,gen) ins(a,n-1); // insert perms into group one by one
- ll tot = 1;
- F0R(i,n) {
- int cnt = 0; F0R(j,i+1) cnt += g[i].flag[j];
- tot *= cnt;
- }
- return tot;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement