[ZOJ 3765 Lights] Splay

来源:互联网 发布:火影忍者手游pk网络卡 编辑:程序博客网 时间:2024/05/23 19:14

[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

数据范围:(1N200000,1Q100000)(1value1090status1)

3. 解题思路

裸的Splay模板。只需要维护value以及区间状态status为0,1gcd0,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;}
1 0
原创粉丝点击