[ZOJ 3765 Lights] Splay
2017-04-21 13:18
232 查看
[ZOJ 3765 Lights] Splay
分类:Data Structure
Splay
1. 题目链接
[ZOJ 3765 Lights]2. 题意描述
有一个长度为n的序列。q次操作。序列中每个元素有两个属性,value和status。有以下几种操作。
查询区间[L,R]范围内状态为status的数的value的gcd;
第i个元素后面插入一个元素
删除第i个元素
将第i个元素的status取反
修改第i个元素的value
数据范围:(1≤N≤200000,1≤Q≤100000),(1≤value≤109,0≤status≤1)
3. 解题思路
裸的Splay模板。只需要维护value以及区间状态status为0,1的gcd0,gcd1即可。注意一下,后面的操作中,会生成一些节点,所以要降数组大小开到300000。
试了一下单旋和双旋,在这个题目里面没有什么区别。
不过,正式比赛的时候千万不要这么zuo,在链式的情况下,单旋之后依旧会是一条链,而双旋之后,链会变成一棵树。只有双旋,才能保证均摊复杂度为O(log2n)
4. 实现代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef long double LB; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; typedef vector<int> VI; const int INF = 0x3f3f3f3f; const LL INFL = 0x3f3f3f3f3f3f3f3fLL; const double eps = 1e-8; const double PI = acos(-1.0); #define Key_value ch[ch[root][1]][0] const int MAXN = 300010; int pre[MAXN], ch[MAXN][2], sz[MAXN]; int root, tot1; int gcd[MAXN][2], stat[MAXN], key[MAXN]; int s[MAXN], tot2; //内存池和容量 int a[MAXN], b[MAXN]; int n, q; //debug部分********************************** void Treavel(int x) { if(x) { Treavel(ch[x][0]); printf("root: %2d: lch %2d rch %2d fa %2d size= %2d\n", x, ch[x][0], ch[x][1], pre[x], sz[x]); Treavel(ch[x][1]); } } void debug() { printf("root:%d\n", root); Treavel(root); } //以上是debug部分************************************** inline void NewNode(int &r, const int& father, const int& ax, const int& bx) { if(tot2) r = s[tot2--]; //取的时候是tot2--,存的时候就是++tot2 else r = ++tot1; pre[r] = father; ch[r][0] = ch[r][1] = 0; key[r] = ax; stat[r] = bx; gcd[r][bx] = ax; gcd[r][!bx] = 0; sz[r] = 1; } inline int m_gcd(const int& ax, const int& bx) { if(ax == 0 && bx == 0) return 0; if(ax == 0) return bx; if(bx == 0) return ax; return __gcd(ax, bx); } inline void pushUp(const int&r) { int lson = ch[r][0], rson = ch[r][1]; sz[r] = sz[lson] + sz[rson] + 1; gcd[r][0] = gcd[r][1] = 0; gcd[r][0] = m_gcd(gcd[lson][0], gcd[rson][0]); gcd[r][1] = m_gcd(gcd[lson][1], gcd[rson][1]); gcd[r][stat[r]] = m_gcd(gcd[r][stat[r]], key[r]); } void Build(int &x, int l, int r, int father) { if(l > r) return; int mid = (l + r) / 2; NewNode(x, father, a[mid], b[mid]); Build(ch[x][0], l, mid - 1, x); Build(ch[x][1], mid + 1, r, x); pushUp(x); } void Init() { root = tot1 = tot2 = 0; ch[root][0] = ch[root][1] = sz[root] = pre[root] = 0; stat[0] = gcd[root][0] = gcd[root][1] = key[root] = 0; NewNode(root, 0, 0, 0); NewNode(ch[root][1], root, 0, 0); for(int i = 0; i < n; i++) scanf("%d %d", &a[i], &b[i]); Build(Key_value, 0, n - 1, ch[root][1]); pushUp(ch[root][1]); pushUp(root); } //旋转,0为左旋,1为右旋 void Rotate(int x, int kind) { int y = pre[x]; ch[y][!kind] = ch[x][kind]; pre[ch[x][kind]] = y; if(pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x; pre[x] = pre[y]; ch[x][kind] = y; pre[y] = x; pushUp(y); } // 将r放到goal下面,, 双旋 void Splay(int r, int goal) { while(pre[r] != goal) { if(pre[pre[r]] == goal) { Rotate(r, ch[pre[r]][0] == r); } else { int y = pre[r]; int kind = ch[pre[y]][0] == y; if(ch[y][kind] == r) { //zig-zag zag-zig Rotate(r, !kind); Rotate(r, kind); } else { //zig-zig zag-zag Rotate(y, kind); Rotate(r, kind); } } } pushUp(r); if(goal == 0) root = r; } // 将r放到goal下面,, 单旋 /* void Splay(int r, int goal) { while(pre[r] != goal) { Rotate(r, ch[pre[r]][0] == r); } pushUp(r); if(goal == 0) root = r; } */ int Kth(int r, int k) { int t = sz[ch[r][0]] + 1; if(t == k) return r; if(t > k) return Kth(ch[r][0], k); else return Kth(ch[r][1], k - t); } void Insert(int pos, int ax, int bx) { Splay(Kth(root, pos + 1), 0); Splay(Kth(root, pos + 2), root); NewNode(Key_value, ch[root][1], ax, bx); pushUp(ch[root][1]); pushUp(root); } void erase(int r) { if(!r)return; s[++tot2] = r; erase(ch[r][0]); erase(ch[r][1]); } void Delete(int pos) { Splay(Kth(root, pos), 0); Splay(Kth(root, pos + 2), root); erase(Key_value); pre[Key_value] = 0; Key_value = 0; pushUp(ch[root][1]); pushUp(root); } void Update_R(int pos) { Splay(Kth(root, pos), 0); Splay(Kth(root, pos + 2), root); stat[Key_value] ^= 1; pushUp(Key_value); pushUp(ch[root][1]); pushUp(root); } void Update_M(int pos, int a) { Splay(Kth(root, pos), 0); Splay(Kth(root, pos + 2), root); key[Key_value] = a; pushUp(Key_value); pushUp(ch[root][1]); pushUp(root); } int Get_Ans(int L, int R, int bx) { Splay(Kth(root, L), 0); Splay(Kth(root, R + 2), root); return gcd[Key_value][bx]; } int main() { #ifdef ___LOCAL_WONZY___ freopen("input.txt", "r", stdin); #endif // ___LOCAL_WONZY___ int L, R, ax, bx, px, ans; char op[10]; while(scanf("%d %d", &n, &q) == 2) { Init(); // debug(); while(q --) { scanf("%s", op); if(op[0] == 'Q') { scanf("%d %d %d", &L, &R, &bx); ans = Get_Ans(L, R, bx); printf("%d\n", ans ? ans : -1); } else if(op[0] == 'I') { scanf("%d %d %d", &px, &ax, &bx); Insert(px, ax, bx); } else if(op[0] == 'D') { scanf("%d", &px); Delete(px); } else if(op[0] == 'R') { scanf("%d", &px); Update_R(px); } else if(op[0] == 'M') { scanf("%d %d", &px, &ax); Update_M(px, ax); } } } #ifdef ___LOCAL_WONZY___ cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl; #endif // ___LOCAL_WONZY___ return 0; }
相关文章推荐
- ZOJ 3765 Lights (SPLAY)
- ZOJ-3765 Lights(Splay树)
- ZOJ 3765 Lights (伸展树splay)
- zoj 3765 Lights(Splay)
- ZOJ 3765 Lights (SPLAY)
- ZOJ 3765 Lights (zju March I)伸展树Splay
- zoj 3765 Lights splay
- ZOJ 3765 —— Lights(伸展树)
- zoj 3765 Lights(伸展树)
- 【splay tree】 ZOJ 3765 Lights
- ZOJ 3765 Lights
- ZOJ 3765 splay
- ZOJ 3765 Lights Splay Tree的几种基本操作
- zoj 3765 Lights(伸展树)
- ZOJ Monthly, March 2014,3765 Lights (Splay 基本操作,并维护区间上的信息 * 模板)
- ZOJ 3765 Lights(SplayTree)
- ZOJ 3765 Lights (伸展树)
- Lights--ZOJ月赛--伸展树
- zoj 3612 Median (splay)
- ZOJ3765 Lights(Splay平衡树)(占位)