http://codevs.cn/problem/1743/
题解:
思路:采用标记的方式减少操作。rev表示该节点及子树需要翻转。如果在kth()查询第k位置的卡片时走到这个节点o,就pushdown(o),把标记传到子节点,反转左右子节点。如果要反转的区间为[l, r],在rever操作中,将l-1伸展到根,再将r+1节点伸展到右节点。那么对应区间可以转化为ch[ch[o][1]][0]节点所对应的树,给它打标记即可。
注意的问题:
1.需要虚拟节点,因为思路中rever操作很有风险。建立虚拟节点后各个点的编号要变。
2.在将某节点伸展到根的右节点时,注意k的取值,要减去根左节点的s值+1。见代码。
3.要注意pushdown操作的位置,共有三处需要:kth中一次,splay中两次。
3.定义了宏,挺好用的。
代码
总时间耗费: 1782ms
总内存耗费: 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;
}
原文地址:http://blog.csdn.net/qq_21110267/article/details/43602153