ZOJ 3765 Lights (伸展树)

伸展树裸题,做了几题后已经不需要调了,像前几次经常调个好久。。听说可持久化treap更好用,调起来方便,下次学一下。

code:

#include 
    
    
     
     
#include 
     
     
      
      
using namespace std;

#define lson x->ch[0]
#define rson x->ch[1]
#define ket (root->ch[1]->ch[0])

const int maxn = 300000+5;

int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }

struct NODE{
    NODE *pre, *ch[2];
    int val, G[2], sz, id, on;

    void up() {
        sz = ch[0]->sz + ch[1]->sz + 1;
        G[on] = gcd(val, gcd(ch[0]->G[on], ch[1]->G[on]));
        G[!on] = gcd(ch[0]->G[!on], ch[1]->G[!on]);
    }
};

struct Splaytree {
    int top;
    NODE node[maxn], *null, *root;

    void Rotate(NODE *x, int c) {
        NODE *y = x->pre;
        y->ch[!c] = x->ch[c];
        if(x->ch[c] != null)    x->ch[c]->pre = y;
        x->pre = y->pre;
        if(y->pre != null)  y->pre->ch[ y->pre->ch[1]==y] = x;
        x->ch[c] = y; y->pre = x;
        y->up();
    }

    void Splay(NODE *x, NODE *go) {
        while(x->pre != go) {
            if(x->pre->pre == go)   Rotate(x, x->pre->ch[0]==x);
            else {
                NODE *y = x->pre, *z = y->pre;
                int f = z->ch[1] == y;
                if(y->ch[f] == x)   Rotate(y, !f);
                else    Rotate(x, f);
                Rotate(x, !f);
            }
        }
        x->up();
        if(go == null)  root = x;
    }

    void RTO(int k, NODE *go) {
        NODE *x = root;
        while(lson->sz != k) {
            if(lson->sz > k)    x = lson;
            else {
                k -= lson->sz + 1;
                x = rson;
            }
        }
        Splay(x, go);
    }

    int a[maxn], b[maxn];

    NODE* newnode(int val, int on, NODE *f) {
        NODE *x = &node[++top];
        x->id = top; x->sz = 1;
        lson = rson = null;
        x->on = on; x->val = x->G[on] = val;
        x->G[!on] = 0; x->pre = f;
        return x;
    }

    NODE *build(int l, int r, NODE *f) {
        if(l > r)   return null;
        int mid = (l + r)/2;
        NODE *x = newnode(a[mid], b[mid], f);
        lson = build(l, mid-1, x);
        rson = build(mid+1, r, x);
        x->up();
        return x;
    }

    void init(int n) {
        null = &node[0];
        null->sz = null->G[0] = null->G[0] = null->val = 0;
        top = 0;
        root = newnode(0, 0, null);
        root->ch[1] = newnode(0, 0, root);
        for(int i = 0;i < n; i++)   scanf("%d%d", &a[i], &b[i]);
        ket = build(0, n-1, root->ch[1]);
        root->ch[1]->up(); root->up();
    }

    void Get(int l, int r) {
        RTO(l-1, null);
        RTO(r+1, root);
    }

    void Query() {
        int l, r, on;
        scanf("%d%d%d", &l, &r, &on);
        Get(l, r);
        int ans = ket->G[on];
        if(!ans)    puts("-1");
        else    printf("%d\n", ans);
    }

    void Insert() {
        int i, val, on;
        scanf("%d%d%d", &i, &val, &on);
        RTO(i, null);
        RTO(i+1, root);
        ket = newnode(val, on, root->ch[1]);
        root->ch[1]->up(); root->up();
    }

    void Delete() {
        int i;
        scanf("%d", &i);
        Get(i, i);
        ket = null;
        root->ch[1]->up(); root->up();
    }

    void RR() {
        int i;
        scanf("%d", &i);
        Get(i, i);
        ket->on ^= 1; swap(ket->G[0], ket->G[1]);
        root->ch[1]->up(); root->up();
    }

    void Modify() {
        int i, v;
        scanf("%d%d", &i, &v);
        Get(i, i);
        ket->val = ket->G[ket->on] = v;
        root->ch[1]->up(); root->up();
    }
}spt;

int main() {
    int n, m;
    while(scanf("%d%d", &n, &m) != -1) {
        spt.init(n);
        for(int i = 0;i < m; i++) {
            char op[5];
            scanf("%s", op);
            if(op[0] == 'Q')    spt.Query();
            else if(op[0] == 'I')   spt.Insert();
            else if(op[0] == 'D')   spt.Delete();
            else if(op[0] == 'R')   spt.RR();
            else spt.Modify();
        }
    }
    return 0;
}

     
     
    
    

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值