@Falsyta
2015-08-10T02:58:23.000000Z
字数 5880
阅读 1298
OI mxh带窝飞
对于给定的
给出一个无向图
给定一个置换
按照
问题转化成构造一个
我们考虑完全图(含自环)有非常适合本题的性质:
我们在完全图下准备一条链一直连到终点,这样我们可以控制可以
令
# include <cstdio># define REP(i, n) for (int i = 1; i <= n; i ++)bool g[100][100];int q0, a[100];long long K;int main (){for (scanf ("%d", &q0); q0; q0 --){scanf ("%I64d", &K);if (!K) {printf ("1 1\n0\n"); continue;}int len = 0;while (K) a[++ len] = K % 10, K /= 10;int n = 10 + len + 1, m = len + 2;REP (i, n) REP (j, n) g[i][j] = (i <= 10 && j <= 10);REP (i, len) {REP (j, a[i]) g[j][10 + i] = 1; g[10 + i][11 + i] = 1;}printf ("%d %d\n", n, m);REP (i, n) {REP (j, n) putchar ('0' + g[i][j]); putchar ('\n');}}return 0;}
……很老旧的LCT思路…………
令每条边为
考虑扫描线,每加一条边,替换掉环上
在线段树上更新答案即可。
时间复杂度
# include <cstdio># include <iostream># include <algorithm># define REP(i, n) for (int i = 1; i <= n; i ++)# define REP_0N(i, n) for (int i = 0; i <= n; i ++)# define FOR(i, a, b) for (int i = a; i <= b; i ++)using namespace std;const int NR = 401000;# define u t[x]# define o t[y]# define lc ch[0]# define rc ch[1]# define tc ch[ty]# define vc ch[!ty]# define ulfc t[u.lc]# define urtc t[u.rc]struct Lct {int ch[2], par, min, val; bool rev; void Rev () {rev ^= 1, swap (lc, rc);} void Set (int q) {min = val = q;}} t[NR];struct Arr {int l, r, id;} q[NR], g[NR];int n, m, q0, den[NR], ans[NR], dsz;bool Cmp (Arr a, Arr b) {if (a.r != b.r) return a.r < b.r; return a.l < b.l;}namespace Se{struct Seg {int ch[2], tag; inline void Add (int d) {tag += d;}} t[NR << 2];int sz;inline void PD (int x) {if (!x || !u.tag) return ; ulfc.Add (u.tag), urtc.Add (u.tag), u.tag = 0;}void Build (int x, int l, int r){u.tag = 0;if (l == r) return ;int mid = (l + r) >> 1;Build (u.lc = ++ sz, l, mid), Build (u.rc = ++ sz, mid + 1, r);}void SegInc (int x, int l, int r, int il, int ir){if (il <= l && r <= ir) {u.Add (1); return ;}PD (x); int mid = (l + r) >> 1;if (il <= mid) SegInc (u.lc, l, mid, il, ir);if (ir > mid) SegInc (u.rc, mid + 1, r, il, ir);}int SegVal (int x, int l, int r, int p){if (l == r) return u.tag;PD (x); int mid = (l + r) >> 1;if (p <= mid) return SegVal (u.lc, l, mid, p);return SegVal (u.rc, mid + 1, r, p);}inline void Inc (int l, int r) {SegInc (1, 1, n, l, r);}inline int Val (int p) {return SegVal (1, 1, n, p);}}# define p u.parinline void PD (int x){if (!x || !u.rev) return ;if (u.lc) ulfc.Rev (); if (u.rc) urtc.Rev (); u.rev = 0;}inline void Upd (int x){u.min = u.val;if (g[ulfc.min].l < g[u.min].l) u.min = ulfc.min;if (g[urtc.min].l < g[u.min].l) u.min = urtc.min;}inline int sgn (int x) {return t[p].rc == x ? 1 : t[p].lc == x ? 0 : -1;}inline void sc (int x, int y, bool ty) {u.tc = y, o.par = x;}inline void Fix (int x) {if (~ sgn (x)) Fix (p); PD (x);}inline void Rot (int x, bool ty){int y = p, z = o.par;if (~ sgn (y)) sc (z, x, sgn (y)); else p = z;sc (y, u.vc, ty), sc (x, y, !ty), Upd (y), Upd (x);}int Splay (int x){Fix (x); int t0, t1, y;while (~ (t0 = sgn (x))){if (~ (t1 = sgn (y = p))) Rot (t0 ^ t1 ? x : y, t0), Rot (x, t1);else Rot (x, t0);}return Upd (x), x;}inline int Acs (int tx) {for (int x = tx, y = 0; x; Upd (y = x), x = p) Splay (x), u.rc = y; return Splay (tx);}# define us t[Acs (x)]inline int gf (int x) {for (Acs (x); PD (x), u.lc; x = u.lc); return x;}inline void Evt (int x) {us.Rev ();}inline void Link (int x, int y) {Evt (x), p = y;}inline void Cut (int x) {t[us.lc].par = 0, u.lc = 0;}inline void Cut (int x, int y) {Evt (x), Cut (y);}inline int Min (int x, int y) {return Evt (y), us.min;}int main (){g[0].l = 1 << 30;while (scanf ("%d%d%d", &n, &m, &q0) != EOF){Se::Build (Se::sz = 1, 1, n);dsz = n;REP_0N (x, n + m) u.lc = u.rc = u.par = u.rev = u.val = u.min = 0;REP (i, m){scanf ("%d%d", &g[i].l, &g[i].r);if (g[i].l > g[i].r) swap (g[i].l, g[i].r);}REP (i, q0) scanf ("%d%d", &q[i].l, &q[i].r), q[i].id = i;sort (g + 1, g + m + 1, Cmp);sort (q + 1, q + q0 + 1, Cmp);int qi = 1; g[m + 1].r = g[0].r = -1;REP (i, m){if (g[i].r != g[i - 1].r)while (qi <= q0 && q[qi].r < g[i].r)ans[q[qi].id] = n - Se::Val (q[qi].l), qi ++;if (gf (g[i].l) != gf (g[i].r)){t[den[i] = ++ dsz].Set (i), Link (den[i], g[i].l), Link (den[i], g[i].r);Se::Inc (1, g[i].l);}else{int d = Min (g[i].l, g[i].r);if (g[d].l < g[i].l){den[i] = den[d];Cut (den[d], g[d].l), Cut (den[d], g[d].r);t[den[i]].Set (i);Link (den[i], g[i].l), Link (den[i], g[i].r);Se::Inc (g[d].l + 1, g[i].l);}}}while (qi <= q0) ans[q[qi].id] = n - Se::Val (q[qi].l), qi ++;REP (i, q0) printf ("%d\n", ans[i]);}return 0;}
考虑贪心地定原置换
位置
有两种情况,
若是最后一个元素,那么第一个值应该在前面。
否则应该是在
注意到环不能嵌套后用线段树与set维护即可。
# include <cstdio># include <iostream># include <algorithm># include <map>using namespace std;# define REP(i, n) for (int i = 1; i <= n; i ++)const int NR = 100100;# define u t[x]# define lc ch[0]# define rc ch[1]# define ulfc t[u.lc]# define urtc t[u.rc]struct Seg {int ch[2], max; bool cov;} t[NR << 2];map <int, int> pos;int n, a[NR], tp[NR], sz, q0, fa[NR];int gf (int x) {return fa[x] == x ? x : (fa[x] = gf (fa[x]));}inline void Upd (int x){u.max = 0;if (a[ulfc.max] > a[u.max]) u.max = ulfc.max;if (a[urtc.max] > a[u.max]) u.max = urtc.max;}int Max (int x, int l, int r, int ql, int qr){if (u.cov) return 0;if (ql <= l && r <= qr) return u.max;int mid = (l + r) >> 1, ret = 0, tmp;if (ql <= mid && a[tmp = Max (u.lc, l, mid, ql, qr)] > a[ret]) ret = tmp;if (qr > mid && a[tmp = Max (u.rc, mid + 1, r, ql, qr)] > a[ret]) ret = tmp;return ret;}void Del (int x, int l, int r, int cl, int cr){if (u.cov) return ;if (cl <= l && r <= cr) {u.cov = 1, u.max = 0; return ;}int mid = (l + r) >> 1, ret = 0;if (cl <= mid) Del (u.lc, l, mid, cl, cr);if (cr > mid) Del (u.rc, mid + 1, r, cl, cr);Upd (x);}int Build (int l, int r){int x = ++ sz, mid = (l + r) >> 1; u.cov = 0;if (l == r) return u.max = l, x;return u.lc = Build (l, mid), u.rc = Build (mid + 1, r), Upd (x), x;}bool Cmp (int i, int j) {return a[i] < a[j];}int main (){for (scanf ("%d", &q0); q0; q0 --){scanf ("%d", &n), sz = 0;REP (i, n) scanf ("%d", &a[i]), tp[i] = i, fa[i] = 0;sort (tp + 1, tp + n + 1, Cmp), Build (1, n);pos.clear (), pos[0] = 0;REP (p, n){int i = tp[p];map <int, int>::iterator it = pos.upper_bound (i); it --;char sc = (p == n ? '\n' : ' ');if (it->first<it->second){printf ("%d%c", a[i + 1], sc);continue;}if (fa[i]){int j = gf (i);if (i == n || pos.find (i + 1) != pos.end () || a[j] > a[i + 1])printf ("%d%c", a[j], sc), pos[i] = j, pos[j] = i;elseDel (1, 1, n, i + 1, i + 1), fa[i + 1] = i, printf ("%d%c", a[i + 1], sc);continue;}int j = Max (1, 1, n, it->first + 1, i);if (i == n || pos.find (i + 1) != pos.end () || a[j] > a[i + 1])Del (1, 1, n, j, i), pos[i] = j, pos[j] = i, printf ("%d%c", a[j], sc);else Del (1, 1, n, i, i + 1), fa[i] = i, fa[i + 1] = i, printf ("%d%c", a[i + 1], sc);}}return 0;}