BZOJ 3223: Tyvj 1729 文艺平衡树
2016-05-11 18:59
211 查看
BZOJ 3223
十分裸的一个splay模板题,标记法处理翻转。
二周目
十分裸的一个splay模板题,标记法处理翻转。
#include<cstdio> #include<algorithm> #include<vector> using namespace std; struct Node { Node *ch[2]; int s; int flip; int v; int cmp(int k) const { int d = k - ch[0]->s; if(d == 1) return -1; return d <= 0 ? 0 : 1; } void maintain() { s = ch[0]->s + ch[1]->s + 1; } void pushdown() { if(flip) { flip = 0; swap(ch[0], ch[1]); ch[0]->flip = !ch[0]->flip; ch[1]->flip = !ch[1]->flip; } } }; Node *null = new Node(); void rotate(Node* &o, int d) { Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o; o->maintain(); k->maintain(); o = k; } void splay(Node* &o, int k) { o->pushdown(); int d = o->cmp(k); if(d == 1) k -= o->ch[0]->s + 1; if(d != -1) { Node* p = o->ch[d]; p->pushdown(); int d2 = p->cmp(k); int k2 = (d2 == 0 ? k : k - p->ch[0]->s - 1); if(d2 != -1) { splay(p->ch[d2], k2); if(d == d2) rotate(o, d^1); else rotate(o->ch[d], d); } rotate(o, d^1); } } // 合并left和right。假定left的所有元素比right小。注意right可以是null,但left不可以 Node* merge(Node* left, Node* right) { splay(left, left->s); left->ch[1] = right; left->maintain(); return left; } // 把o的前k小结点放在left里,其他的放在right里。1<=k<=o->s。当k=o->s时,right=null void split(Node* o, int k, Node* &left, Node* &right) { splay(o, k); left = o; right = o->ch[1]; o->ch[1] = null; left->maintain(); } const int maxn = 100000 + 10; struct SplaySequence { int n; Node seq[maxn]; Node *root; Node* build(int sz) { if(!sz) return null; Node* L = build(sz/2); Node* o = &seq[++n]; o->v = n; // 节点编号 o->ch[0] = L; o->ch[1] = build(sz - sz/2 - 1); o->flip = o->s = 0; o->maintain(); return o; } void init(int sz) { n = 0; null->s = 0; root = build(sz); } }; vector<int> ans; void print(Node* o) { if(o != null) { o->pushdown(); print(o->ch[0]); ans.push_back(o->v); print(o->ch[1]); } } void debug(Node* o) { if(o != null) { o->pushdown(); debug(o->ch[0]); printf("%d ", o->v-1); debug(o->ch[1]); } } SplaySequence ss; int main() { freopen("p3223.in", "r", stdin); int n, m; scanf("%d%d", &n, &m); ss.init(n+1); // 最前面有一个虚拟结点 while (m--) { int a, b; scanf("%d%d", &a, &b); Node *left, *mid, *right, *o; split(ss.root, a, left, o); // 如果没有虚拟结点,a将改成a-1,违反split的限制 split(o, b-a+1, mid, right); mid->flip ^= 1; ss.root = merge(merge(left, mid), right); } print(ss.root); for(int i = 1; i < ans.size(); i++) printf("%d ", ans[i]-1); // 节点编号减1才是本题的元素值 retur 4000 n 0; }
二周目
#include<cstdio> #include<iostream> #include<algorithm> #include<cstdlib> #include<vector> using namespace std; struct Node{ Node* ch[2]; int v, s, flag; int cmp(int k) const{ int d = k - ch[0]->s; if(d == 1) return -1; return d <= 0 ? 0 : 1; } void pushdown(){ if(flag){ flag = 0; swap(ch[0], ch[1]); ch[0]->flag ^= 1; ch[1]->flag ^= 1; } } void maintain(){ s = ch[0]->s + ch[1]->s + 1; } }; Node* null = new Node(); void rotate(Node* &o, int d){ Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o; o->maintain(); k->maintain(); o = k; } void splay(Node* &o, int k){ o->pushdown(); int d = o->cmp(k); if(d == 1) k -= o->ch[0]->s + 1; if(d != -1){ Node* p = o->ch[d]; p->pushdown(); int d2 = p->cmp(k); int k2 = (d2 == 0 ? k : k - p->ch[0]->s - 1); if(d2 != -1){ splay(p->ch[d2], k2); if(d == d2) rotate(o, d^1); else rotate(o->ch[d], d); } rotate(o, d^1); } } Node* merge(Node* left, Node* right){ splay(left, left->s); left->ch[1] = right; left->maintain(); return left; } void split(Node* o, int k, Node* &left, Node* &right){ splay(o, k); left = o; right = o->ch[1]; o->ch[1] = null; left->maintain(); } struct Splay{ Node* root; int n; Node* build(int sz){ if(!sz) return null; Node* o = new Node(); o->ch[0] = build(sz/2); o->v = ++n; o->flag = o->s = 0; o->ch[1] = build(sz - sz/2 - 1); o->maintain(); return o; } void init(int sz){ n = 0; null->s = 0; root = build(sz); } vector<int> ans; void outit(Node* o){ if(o != null){ o->pushdown(); outit(o->ch[0]); ans.push_back(o->v); outit(o->ch[1]); } } } tr; int n, m; int main(){ freopen("p3223.in", "r", stdin); scanf("%d%d", &n, &m); tr.init(n+1); int l, r; while(m--){ scanf("%d%d", &l, &r); Node *left, *right, *mid, *o; split(tr.root, l, left, o); split(o, r-l+1, mid, right); mid->flag ^= 1; tr.root = merge( merge(left, mid), right ); } tr.outit(tr.root); for(int i = 1; i < tr.ans.size(); i++) printf("%d ", tr.ans[i] - 1); cout<<endl; return 0; }
相关文章推荐
- svn
- C# 中的委托和事件
- swift 中showAlertTitle的使用
- HDU2149(巴什博弈Bash Game)
- Django登录、注册、退出
- 深入javascript
- iOS Ad hoc
- Android通用流行框架大全
- XStream4Java高级应用
- 【BZOJ-3631】松鼠的新家 树形DP?+ 倍增LCA + 打标记
- android Activity runOnUiThread() 方法使用
- Android 热修复Nuwa的原理及Gradle插件源码解析
- js 二维数组的深拷贝
- android学习之AIDL初探
- 记我的第一次继承spring和hibernate
- 如何判断一个js对象是否一个DOM对象
- Linux下的SVN服务器搭建
- 【BaiduMapSDK系列】baidumapsdk: Authentication Error errorcode: 230 uid: -1 appid -1 msg: APP Scode码校验失败
- Pragmatic Scala:Create Expressive, Concise, and Scalable Applications (读书笔记)
- 二叉树的12大问题