Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- using ll = long long;
- #define pb emplace_back
- #define AI(i) begin(i), end(i)
- template<class T> bool chmin(T &a, T b) { return b < a && (a = b, true); }
- template<class T> bool chmax(T &a, T b) { return a < b && (a = b, true); }
- #ifdef KEV
- #define DE(args...) kout("[ " + string(#args) + " ] = ", args)
- void kout() { cerr << endl; }
- template<class T, class ...U> void kout(T a, U ...b) { cerr << a << ' ', kout(b...); }
- template<class T> void debug(T l, T r) { while (l != r) cerr << *l << " \n"[next(l)==r], ++l; }
- #else
- #define DE(...) 0
- #define debug(...) 0
- #endif
- const int MAX_N = 1e5 + 100, p = 1e9 + 7;
- void mul(ll &a, ll b) { a = a * b % p; }
- int rand() {
- static unsigned x = 1923847;
- return (++x) *= 0xdefaced;
- }
- namespace TP {
- struct node {
- int sz, pa, pri, l, r;
- }room[MAX_N];
- #define exp(a) int& a(int i){ return room[i].a; }
- exp(sz);
- exp(pa);
- exp(pri);
- exp(l);
- exp(r);
- void init(int n) {
- // 0 is null
- for (int i = 1;i < n + 10;++i) {
- pri(i) = rand();
- pa(i) = i;
- sz(i) = 1;
- }
- }
- void upd(int x) {
- if (x == 0) return;
- sz(x) = sz(l(x)) + sz(r(x)) + 1;
- pa(x) = pa(l(x)) = pa(r(x)) = x;
- }
- // cut exactly k stuff
- void split_sz(int x, int k, int &a, int &b) {
- if (x == 0) {
- a = b = 0;
- return;
- }
- if (sz(l(x)) + 1 <= k) {
- a = x;
- split_sz(r(x), k - sz(l(x)) - 1, r(a), b);
- }
- else {
- b = x;
- split_sz(l(x), k, a, l(b));
- }
- upd(a), upd(b);
- }
- void DB(int x) {
- if (x == 0) return;
- DB(l(x));
- cerr << x << ' ';
- DB(r(x));
- }
- int merge(int a, int b) {
- if (!a || !b) return a + b;
- if (pri(a) < pri(b)) {
- r(a) = merge(r(a), b);
- upd(a);
- return a;
- }
- else {
- l(b) = merge(a, l(b));
- upd(b);
- return b;
- }
- }
- // first is rank, second is boss
- // rank is how many stuff is smaller
- pair<int,int> getrb(int x) {
- if (pa(x) == x) return make_pair(0, x);
- auto [rk, bs] = getrb(pa(x));
- if (x == l(pa(x)))
- return make_pair(rk - sz(r(x)) - 1, bs);
- else
- return make_pair(rk + sz(l(x)) + 1, bs);
- }
- }
- int inv[MAX_N];
- void init_math() {
- inv[0] = inv[1] = 1;
- for (int i = 2;i < MAX_N;++i)
- inv[i] = (ll)(p - p/i) * inv[p % i] % p;
- }
- struct get_pfac {
- vector<int> minp, pnum;
- vector<vector<pair<int,int>>> tab;
- vector<pair<int,int>> hp(int v) {
- vector<pair<int,int>> ret;
- while (v > 1) {
- int f = minp[v];
- if (ret.size() && ret.back().first == f) ret.back().second *= f;
- else ret.pb(f, f);
- v /= f;
- }
- return ret;
- }
- get_pfac(int n = 0) {
- n += 10;
- minp.resize(n);
- for (int i = 2;i < n;++i) {
- if (minp[i] == 0) {
- minp[i] = i;
- pnum.pb(i);
- for (int j : pnum) {
- if ((ll)i * j >= n) break;
- minp[i * j] = j;
- if (j % i == 0) break;
- }
- }
- }
- minp[1] = minp[0] = 1;
- tab.resize(n);
- for (int i = 2;i < n;++i)
- tab[i] = hp(i);
- }
- vector<pair<int,int>> operator ()(int v) { return tab[v]; }
- };
- struct lcms {
- vector<multiset<int>> cnt;
- vector<vector<pair<int,int>>> pfac;
- get_pfac hp;
- ll res = 1;
- lcms(int n) {
- cnt.resize(n + 10);
- pfac.resize(n + 10);
- for (auto &i : cnt)
- i.insert(1);
- hp = get_pfac(n);
- }
- void add(int i, int t) {
- DE(i, t);
- for (auto [f, c] : hp(i)) {
- mul(res, inv[ *cnt[f].rbegin() ]);
- if (t == 1) cnt[f].insert(c);
- else cnt[f].erase(cnt[f].find(c));
- mul(res, *cnt[f].rbegin());
- }
- }
- };
- int32_t main() {
- ios_base::sync_with_stdio(0), cin.tie(0);
- init_math();
- int n, q;
- cin >> n >> q;
- TP::init(n);
- lcms LC(n);
- vector<int> nxt(n + 1); iota(AI(nxt), 0);
- auto doop = [&](int a, int b) {
- int oa = a, ob = b;
- a = nxt[a], b = nxt[b];
- auto [r1, b1] = TP::getrb(a);
- auto [r2, b2] = TP::getrb(b);
- DE(oa, ob);
- if (b1 == b2) {
- TP::DB(b1);
- LC.add(TP::sz(b1), -1);
- if (r1 > r2) swap(r1, r2), swap(a, b);
- int A, B, C, D, E;
- TP::split_sz(b1, r2, D, C);
- TP::split_sz(D, r1, A, B);
- TP::merge(A, C);
- tie(r1, b1) = TP::getrb(a);
- tie(r2, b2) = TP::getrb(b);
- //DE(b1, b2, TP::sz(b1), TP::sz(b2));
- TP::DB(b1), cerr << endl, TP::DB(b2), cerr << endl;
- LC.add(TP::sz(b1), 1);
- LC.add(TP::sz(b2), 1);
- }
- else {
- LC.add(TP::sz(b1), -1);
- LC.add(TP::sz(b2), -1);
- int A, B, C, D;
- TP::split_sz(b1, r1, A, B);
- TP::split_sz(b2, r2, C, D);
- DE(b);
- cerr << "DEA " << endl;
- TP::DB(D);
- DE(A, B, C, D);
- A = TP::merge(A, D);
- A = TP::merge(A, C);
- A = TP::merge(A, B);
- tie(r1, b1) = TP::getrb(a);
- LC.add(TP::sz(b1), 1);
- TP::DB(b1);
- cerr << endl;
- }
- swap(nxt[oa], nxt[ob]);
- };
- while (q--) {
- int a, b;
- cin >> a >> b;
- doop(a, b);
- DE(a, b);
- debug(AI(nxt));
- cout << LC.res << '\n';
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement