[Codevs 1743] Reverse card, codevs1743
Http://codevs.cn/problem/1743/
Question:
Train of Thought: reduce operations by marking. Rev indicates that the node and subtree need to be flipped. If you go to this node o when you query the card at the k position in kth (), pushdown (o) will send the mark to the subnode and reverse the Left and Right subnodes. If the range to be reversed is [l, r], in the rever operation, the l-1 will be stretched to the root, and then the r + 1 node will be stretched to the right node. Then the corresponding interval can be converted to the tree corresponding to the ch [ch [o] [1] [0] node and marked for it.
Notes:
1. virtual nodes are required because rever operations are highly risky. After a virtual node is created, the number of each vertex changes.
2. When stretching a node to the right node of the root node, note that the value of k must be subtracted from the value of s + 1 of the Left node of the root node. See the code.
3. Pay attention to the position of the pushdown operation. There are three requirements: one in kth and two in splay.
3. It is quite useful to define macros.
Code
Total time consumption: 1782 ms
Total memory consumption: 5 MB
#include<cstdio>#include<algorithm>using namespace std;const int maxn = 300000 + 10;const int maxc = 100000;int n, root, ch[maxn][2], s[maxn], v[maxn];bool rev[maxn];#define lc ch[o][0]#define rc ch[o][1]void update(int o) { s[o] = s[lc] + s[rc] + 1; }void rotate(int& o, int d) { int k = ch[o][d^1]; ch[o][d^1] = ch[k][d]; ch[k][d] = o; update(o); update(k); o = k;}void pushdown(int o) { rev[o]^=1; rev[lc]^=1; rev[rc]^=1; swap(lc, rc); }int cmp(int o, int k) { if(s[lc]+1 == k) return -1; return k < s[lc]+1 ? 0 : 1; }void splay(int& o, int k) { if(rev[o]) pushdown(o); //notice int d = cmp(o, k); if(d == -1) return; if(d == 1) k -= s[lc] + 1; int p = ch[o][d]; if(rev[p]) pushdown(p); //notice int d2 = cmp(p, k); int k2 = (d2 == 0) ? k : k-s[ch[p][0]]-1; if(d2 != -1) { splay(ch[p][d2], k2); if(d == d2) rotate(o, d^1); else rotate(ch[o][d], d); } rotate(o, d^1);}void rever(int& o, int L, int R) { splay(o, L); splay(rc, R-s[lc]+1); //R+2 - (s[lc]+1) rev[ch[rc][0]] ^= 1; }void build(int L, int R, int P, int d) { if(L == R) { s[L] = 1; ch[P][d] = L; return; } int M = (L+R) >> 1; if(M-1 >= L) build(L, M-1, M, 0); if(R >= M+1) build(M+1, R, M, 1); ch[P][d] = M; update(M);}int kth(int o, int k) { if(rev[o]) pushdown(o); if(s[lc]+1 == k) return o; if(s[lc] >= k) return kth(lc, k); return kth(rc, k-s[lc]-1);}int main() { scanf("%d", &n); for(int i = 2; i <= n+1; i++) scanf("%d", &v[i]); build(1, n+2, 0, 0); root = (n+3) >> 1; int first, c = 0; while((first = v[kth(root, 2)]) != 1) { rever(root, 1, first); if(++c > maxc) { c = -1; break; } } printf("%d\n", c); return 0;}