Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <iostream>
- #include <algorithm>
- #include <cstring>
- #include <string>
- #include <vector>
- #include <set>
- #include <map>
- #include <utility>
- #include <cstdlib>
- #include <memory>
- #include <queue>
- #include <cassert>
- #include <cmath>
- #include <ctime>
- #include <complex>
- #include <bitset>
- #include <fstream>
- #include <unordered_map>
- #include <unordered_set>
- #include <numeric>
- using namespace std;
- #define ws ws_____________________
- #define y1 y1_____________________
- #define y0 y0_____________________
- #define left left_________________
- #define right right_______________
- #define next next_________________
- #define prev prev_________________
- #define hash hash_________________
- #define pb push_back
- #define fst first
- #define snd second
- #define mp make_pair
- #define sz(C) ((int) (C).size())
- #define forn(i, n) for (int i = 0; i < int(n); ++i)
- #define ford(i, n) for (int i = int(n) - 1; i >= 0; --i)
- #define all(C) begin(C), end(C)
- typedef long long ll;
- typedef unsigned long long ull;
- typedef unsigned int uint;
- typedef pair<int,int> pii;
- typedef pair<ll, ll> pll;
- typedef vector<ll> vll;
- typedef vector<int> vi;
- typedef vector<vi> vvi;
- typedef vector<pii> vii;
- typedef long double ld;
- typedef complex<double> cd;
- #ifdef LOCAL
- #define eprintf(args...) fprintf(stderr, args), fflush(stderr)
- #else
- #define eprintf(...) ;
- #endif
- #define FILE_NAME "a"
- const int N = (int)1e8;
- char Memory[N];
- int curpos = 0;
- void operator delete (void *p) {}
- void* operator new (size_t len)
- {
- assert(curpos + len < N);
- char* ans = (Memory + curpos);
- curpos += len;
- return ans;
- }
- struct Seg {
- int num;
- int l, r;
- int len() const {
- return r - l + 1;
- }
- };
- int m, n;
- vector<Seg> segs;
- bool read() {
- if (scanf("%d%d", &m, &n) < 2) {
- return 0;
- }
- vi C(m);
- vi P(m);
- forn(i, m) {
- scanf("%d%d", &C[i], &P[i]);
- }
- segs.clear();
- segs.pb(Seg{0, 0, 0});
- for (int i = 0, j = 0; i < m; i = j) {
- if (C[i] == -1) {
- j = i + 1;
- continue;
- }
- while (j < m && C[j] == C[i]) {
- ++j;
- }
- segs.pb(Seg{C[i], i + 1, j});
- }
- segs.pb(Seg{n + 1, m + 1, m + 1});
- n += 2;
- m += 1;
- assert(sz(segs) == n);
- return 1;
- }
- struct FenwTree {
- vi t;
- FenwTree(int n = 0) {
- t.assign(n, -1);
- }
- void upd(int pos, int val) {
- for (int i = pos; i < sz(t); i |= i + 1) {
- t[i] = max(t[i], val);
- }
- }
- int get(int r) {
- r = min(r, sz(t) - 1);
- int ans = -1;
- for (int i = r; i >= 0; i &= i + 1, --i) {
- ans = max(ans, t[i]);
- }
- return ans;
- }
- };
- struct SegmTree {
- vector<FenwTree> t;
- vvi vals;
- int sz;
- SegmTree() {}
- SegmTree(const vi& a) {
- sz = 1;
- while (sz < sz(a)) sz *= 2;
- t.resize(sz * 2);
- vals.resize(sz * 2);
- forn(i, sz(a)) {
- vals[sz + i].pb(a[i]);
- }
- for (int v = sz - 1; v > 0; --v) {
- vals[v].resize(sz(vals[v * 2]) + sz(vals[v * 2 + 1]));
- merge(all(vals[v * 2]), all(vals[v * 2 + 1]), vals[v].begin());
- t[v] = FenwTree(sz(vals[v]));
- }
- for (int v = sz; v < sz * 2; ++v) {
- t[v] = FenwTree(1);
- }
- }
- int get_pos(int v, int who) {
- const int p = lower_bound(all(vals[v]), who) - vals[v].begin();
- return sz(vals[v]) - p - 1;
- }
- void upd(int v, int tl, int tr, int pos, int val, int func) {
- const int who = vals[sz + pos].front();
- const int p = get_pos(v, who);
- t[v].upd(p, func);
- if (tl == tr) {
- return;
- }
- int tm = (tl + tr) >> 1;
- if (pos <= tm) {
- upd(v * 2, tl, tm, pos, val, func);
- } else {
- upd(v * 2 + 1, tm + 1, tr, pos, val, func);
- }
- }
- void upd(int pos, int val, int func) {
- upd(1, 0, sz - 1, pos, val, func);
- }
- int get_max(int v, int tl, int tr, int l, int r, int val) {
- l = max(l, tl);
- r = min(r, tr);
- if (l > r) {
- return -1;
- }
- if (l == tl && r == tr) {
- const int p = get_pos(v, val);
- return t[v].get(p);
- }
- int tm = (tl + tr) >> 1;
- int ans = max(get_max(v * 2, tl, tm, l, r, val), get_max(v * 2 + 1, tm + 1, tr, l, r, val));
- return ans;
- }
- int get_max(int l, int r, int val) {
- return get_max(1, 0, sz - 1, l, r, val);
- }
- };
- vi len_seg;
- vi pref;
- void solve() {
- len_seg.assign(n, 0);
- forn(i, n) {
- len_seg[segs[i].num] = (i == 0 || i == n - 1) ? 0 : segs[i].len();
- }
- vi pos_seg(n);
- forn(i, n) {
- pos_seg[segs[i].num] = i;
- }
- pref.assign(n + 1, 0);
- forn(i, n) {
- pref[i + 1] = pref[i] + len_seg[i];
- }
- vi vals(n);
- forn(i, n) {
- vals[i] = pref[i + 1] - (segs[pos_seg[i]].r + 1);
- }
- vi dp(n);
- SegmTree T(vals);
- for (const auto& seg : segs) {
- const int y = seg.num;
- dp[y] = T.get_max(0, y - 1, pref[y] - seg.l);
- if (dp[y] != -1 && seg.num != 0 && seg.num != n - 1) {
- dp[y] += seg.len();
- }
- if (y == 0) {
- dp[y] = 0;
- }
- T.upd(y, vals[y], dp[y]);
- }
- vector<Seg> final_segs;
- int y = n - 1;
- while (y != 0) {
- int best_x = -1;
- for (int x = y - 1; x >= 0; --x) {
- if (pref[x] > pref[y]) {
- continue;
- }
- if (pref[y] - (segs[pos_seg[y]].l) > pref[x + 1] - (segs[pos_seg[x]].r + 1)) {
- continue;
- }
- int ndp = dp[x];
- if (ndp != -1 && y != 0 && y != n - 1) {
- ndp += segs[pos_seg[y]].len();
- }
- if (ndp == dp[y]) {
- best_x = x;
- break;
- }
- }
- assert(best_x != -1);
- final_segs.pb(segs[pos_seg[y]]);
- y = best_x;
- }
- final_segs.pb(segs.front());
- reverse(all(final_segs));
- vi go(m, -1);
- vi go_in(m, -1);
- forn(i, sz(final_segs) - 1) {
- int num0 = final_segs[i].num + 1;
- int num1 = final_segs[i + 1].num - 1;
- int ptr = final_segs[i].r + 1;
- for (int num = num0; num <= num1; ++num) {
- int p = pos_seg[num];
- for (int i = segs[p].l; i <= segs[p].r; ++i) {
- go[i] = ptr;
- go_in[ptr] = i;
- ++ptr;
- }
- }
- }
- vvi ans;
- forn(i, m) {
- if (go_in[i] == -1 && go[i] != -1) {
- vi who;
- int j = i;
- while (j != -1) {
- who.pb(j);
- j = go[j];
- }
- for (int j : who) {
- go[j] = -1;
- go_in[j] = -1;
- }
- ans.pb(who);
- }
- }
- // go[0] = 1;
- // go[1] = 2;
- // go[2] = 0;
- forn(i, m) {
- if (go[i] != -1) {
- vi who;
- int j = i;
- while (go[j] != i) {
- who.pb(j);
- j = go[j];
- }
- who.pb(j);
- who.pb(i);
- for (int j : who) {
- go[j] = -1;
- go_in[j] = -1;
- }
- ans.pb(who);
- }
- }
- int ans_sum = 0;
- for (const auto& c : ans) {
- ans_sum += sz(c) - 1;
- }
- printf("%d %d\n", ans_sum, sz(ans));
- for (const auto& c : ans) {
- printf("%d ", sz(c));
- for (int x : c) {
- printf("%d ", x);
- }
- printf("\n");
- }
- }
- int main() {
- #ifdef LOCAL
- freopen(FILE_NAME ".in", "r", stdin);
- // freopen(FILE_NAME ".out", "w", stdout);
- #else
- // freopen("input.txt", "r", stdin);
- // freopen("output.txt", "w", stdout);
- #endif
- while (read()) {
- solve();
- }
- #ifdef LOCAL
- cerr.precision(5);
- cerr << "Time: " << fixed << (double) clock() / CLOCKS_PER_SEC << endl;
- #endif
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement